You’ve outgrown your first Docker host, you’re rebuilding Proxmox nodes, or you just want to move a stack to a beefier server without starting from scratch. Migrating Docker containers between hosts is a task every homelab operator eventually faces, and doing it wrong means losing persistent data, breaking DNS, or forgetting critical .env files.
This guide covers three migration methods — volume-level, NFS-based zero-copy, and full-environment rsync — with real commands and a complete workflow example. By the end you’ll know exactly how to move any container or Compose stack between hosts cleanly.
All commands target Debian 12 / Ubuntu 24.04 with Docker Engine 27+ and Docker Compose v2.
1. When and Why You Migrate
Migration scenarios in a homelab typically fall into one of three buckets:
- Server upgrade — replacing an older LXC or VM with a newer Proxmox host
- Hardware failure — a disk is failing, ZFS pool is degrading, move services off fast
- Rebalancing — spreading workloads across multiple hosts to avoid resource contention
The core challenge is always the same: containers are ephemeral, but the data they write — databases, uploaded files, configuration — is not. A well-planned migration treats the container as disposable and the data as precious.
2. Strategy Overview — Three Migration Methods
| Method | Downtime | Complexity | Best For |
|---|---|---|---|
| Volume backup/restore | Medium (minutes) | Low | Single containers, small stacks |
| NFS zero-copy | Low (seconds) | Medium | Services with shared storage |
| Full /var/lib/docker rsync | High (10-30 min) | Low | Full environment rebuilds |
Picking the right method depends on how much downtime you can tolerate and how much data you’re moving.
3. Method A — Container-Level Migration with Volume Backup
This is the most portable approach. You back up each named volume as a compressed tarball, save the container image, and re-create the container on the new host.
Backup Volumes
|
|
For bind mounts, you can tar the host path directly:
|
|
Save and Compress Images
|
|
If you have a local registry, push images instead for a faster transfer:
|
|
Transfer and Restore on the New Host
|
|
Deploy the Container
Keep your docker-compose.yml in version control so it’s already on the new host:
|
|
|
|
4. Method B — NFS-Based Zero-Copy Migration
If your homelab already uses NFS (see our NFS storage homelab guide), you can migrate without copying a single byte of application data. The idea is simple: mount the same NFS export on both hosts, and all you move is the container runtime.
NFS Volume in a Compose File
|
|
Migration Sequence
|
|
The data stays mounted on the NFS share the entire time. Downtime is only the time it takes for docker compose down and docker compose up -d — typically under 10 seconds. This works best for stateless or NFS-friendly services like Prometheus, Loki, Grafana, and Pi-hole.
Caveat: Databases (PostgreSQL, MariaDB) should not use NFS as their primary data store without proper sync/fsync tuning. For those, use Method A with a proper dump.
5. Method C — Full Docker Environment Migration
When you’re replacing a host entirely or the old host is failing, you can rsync the entire Docker data directory. This is brute-force but works.
|
|
Optimisation tip: Exclude the overlay2 directory (container layers) if you plan to pull fresh images on the target. This saves gigabytes of transfer time:
|
|
After rsync, run docker image ls and docker volume ls on the target to verify everything arrived. Start containers with docker start $(docker ps -aq) or your Compose stack.
6. Database Migration Considerations
Databases are the most sensitive part of any migration. Use application-aware dumps:
PostgreSQL:
|
|
MariaDB / MySQL:
|
|
SQLite:
|
|
Redis:
|
|
Never raw-copy a database volume without stopping the container first — you risk silent corruption from in-flight writes.
7. Network Identity After Migration
Containers that rely on static IPs (macvlan, ipvlan) lose their network identity when they move.
Macvlan / Static IPs
If your container uses a macvlan network for LAN access, the IP must be available on the target host’s network. Update your DHCP reservation or adjust the Compose config:
|
|
DNS and Traefik
Most homelab stacks front services through Traefik or Nginx. Since Traefik routers are configured in Compose labels, they travel with the stack. The only DNS change is updating your domain’s A record or internal DNS to point to the new host IP.
8. Migration Checklist
Before you start pulling the plug, run through this checklist:
- Backup all named volumes to compressed tar files
- Export container images or push to a private registry
- Copy
.envfiles and any secrets referenced in Compose - Verify volume mount paths exist on the target host
- Update DNS records or reverse proxy rules for the new IP
- Test a single non-critical service first
- Keep the old host running for a 24-hour rollback window
9. Real-World Example: Migrate Traefik + Grafana + Prometheus
Here’s a complete migration of a monitoring stack from a source LXC (10.0.20.30) to a new host (10.0.20.31):
|
|
Total downtime: approximately 3-5 minutes. Rollback is just reversing the process on the old host.
10. Summary
Docker container migration doesn’t have to be stressful. Pick the method that fits your stack:
- Volume backup/restore for most single-container and small-stack moves
- NFS zero-copy for large data sets and minimal downtime
- Full rsync for whole-environment migrations
The most important rule: test your restore process on a throwaway host before doing it for real. Practise the migration with a non-critical service first, then scale up. Keep old hosts around for at least 24 hours post-migration, and version-control your Compose files so you’re never hunting for configs after the move.
For automated volume backups, check out our restic Docker backup guide — it pairs perfectly with the migration and restore workflows covered here.