How to Migrate Docker Containers Between VPS Hosts with Zero Config Loss

tug.sh Team
Core Team
Every engineering team eventually faces the migration dilemma: your current VPS host is running out of disk space, prices have spiked, hardware needs an upgrade, or you want to relocate closer to your target audience.
While moving a stateless application is as simple as running docker compose up on a new box, moving stateful production containers (like databases, content management systems, or storage engines) is notoriously stressful.
In this guide, we'll walk through what makes container migration difficult, the manual steps required to move containers without losing configuration, and how modern platforms automate the process.
Why Manual Container Migration Is Painful
A Docker container isn't just an image. In production, a running container consists of:
- Persistent Volumes: Data directories containing database tables, user uploads, and internal configurations.
- Environment Variables: API keys, database credentials, and operational flags that may not be tracked in version control.
- Network Topology & Port Mappings: Internal bridges, custom IP ranges, exposed host ports, and reverse proxy routes.
- Compose Labels: Metadata used by reverse proxies (like Traefik, Caddy, or Nginx) to automatically route domain traffic.
If any single piece of this puzzle is missing when launching on the destination host, your application will either crash on boot or serve empty data.
Step 1: Preflight Verification Before Moving
Never start a migration without verifying target host readiness:
# Verify Docker engine version and socket accessibility on the destination VPS
ssh user@target-vps "docker info --format '{{.ServerVersion}}'"
# Check available disk space on destination root and volume mount partitions
ssh user@target-vps "df -h /var/lib/docker"
Common pitfalls caught during preflight:
- Port Collisions: Another container on the destination host is already binding port
80,443, or5432. - Insufficient Storage: The database volume is 40GB, but the destination VPS only has 25GB free space.
- Architecture Mismatches: Moving an
amd64container image to anarm64VPS without a multi-arch manifest.
Step 2: Preserving Persistent Volume Data
To migrate stateful volume data safely, you must ensure that no active writes corrupt the archive.
Option A: Manual Volume Sync using Rsync over SSH
- Pause or stop writes on the source container:
docker stop my-postgres-db - Locate the volume path on the source VPS:
docker volume inspect my-postgres-db_data --format '{{.Mountpoint}}' # Outputs e.g. /var/lib/docker/volumes/my-postgres-db_data/_data - Synchronize the volume to the target VPS:
rsync -avzP --numeric-ids /var/lib/docker/volumes/my-postgres-db_data/_data/ \ user@target-vps:/var/lib/docker/volumes/my-postgres-db_data/_data/
Warning: Always preserve file permissions and numeric ownership (
--numeric-ids) withrsync. Otherwise, container users likepostgres(UID 999) won't have write access to the transferred files.
Step 3: Transferring Environment Variables and Configuration
Next, you need to recreate the container specification on the target machine:
# Export the running container inspection JSON
docker inspect my-postgres-db > container-spec.json
From this JSON, you must extract:
Config.Env: All runtime environment variables.HostConfig.Binds: Volume mappings.HostConfig.PortBindings: Host-to-container port routes.Config.Labels: Custom reverse proxy routing labels.
Manually writing a new docker run or docker-compose.yml file from inspection JSON is tedious and error-prone. A single missed typo in an environment variable can break application boot.
Step 4: The 1-Click Way: tug.sh Cross-VPS Migration
Because manual migration requires multiple terminal windows, SSH key setup between servers, volume rsync scripts, and downtime, we built Cross-VPS Live Migration directly into tug.sh:
- Select Source and Destination: Choose any connected VPS from your dashboard dropdown.
- Automated Preflight: tug.sh agents verify SSH authentication, port availability, disk capacity, and architecture compatibility.
- Config Preservation: The agent automatically packages volume checkpoints, environment secrets, and compose labels.
- Transfer & Health Verification: Data is securely streamed directly between nodes, the container is started on the target host, and TugShield verifies that firewall rules allow traffic.
- Rollback Safety: The source container remains intact until you explicitly confirm healthy operation on the new host.
Conclusion
Migrating containers between VPS hosts shouldn't require an afternoon of stressful terminal commands and data loss anxiety. By validating target capacity, maintaining volume permissions, and preserving complete environment configurations, you can move workloads smoothly and keep downtime to seconds.