Migrating a Docker volume between hosts moves persistent container data without depending on the source host's local storage layout. The usual pattern is to stop the writer, export the named volume to a portable tar archive, copy that archive to the destination host, and restore it into a new volume there.
Named volumes are local resources on each Docker host, so the destination machine cannot read the source host's volume directly. A short-lived helper container can mount the volume with --mount, write the archive into a host directory, and then unpack that same archive into a destination volume without needing the application image itself.
The flow below was verified against current Docker Engine volume behavior using a standard local named volume and an alpine helper container. Stop every container that writes to the source volume before exporting it, restore only into a new or empty destination volume, and keep the same container mount path on the receiving workload so the migrated files appear where the application expects them.
Steps to migrate a Docker volume between hosts:
- Stop the container that writes to the source volume so the archive is taken from a consistent on-disk state.
$ docker container stop notes-db notes-db
If multiple containers write to the same volume, stop all of them before exporting it.
Leaving an active writer running during the export can capture half-written files or application state that does not replay cleanly on the destination host.
- Create a host directory on the source machine for the exported archive.
$ mkdir -p /srv/docker-backups
The helper container mounts this directory as a bind mount so the tarball lands on the host instead of inside a disposable container filesystem.
- Export the named volume into a compressed tar archive from a short-lived helper container.
$ docker run --rm --mount source=notes-data,target=/from --mount type=bind,src=/srv/docker-backups,dst=/backup alpine tar -czf /backup/notes-data.tar.gz -C /from .
Docker documentation currently prefers --mount over -v because it is more explicit and supports the full set of volume options.
- List the archive contents before copying it away from the source host.
$ tar -tzf /srv/docker-backups/notes-data.tar.gz ./ ./app.sqlite ./settings.ini ./uploads/ ./uploads/readme.txt
This quick check confirms that the tarball contains the expected volume paths before the transfer step begins.
- Create the same archive directory on the destination host so the transferred tarball has a predictable landing path.
$ ssh admin@docker-b.example.com mkdir -p /srv/docker-backups
- Copy the archive from the source host to the destination host.
$ scp /srv/docker-backups/notes-data.tar.gz admin@docker-b.example.com:/srv/docker-backups/
Replace admin, docker-b.example.com, and the host path with the real destination values used in the environment.
- Create the destination volume on the receiving host before restoring the archive into it.
$ docker volume create notes-data notes-data
Restore into a new or empty volume only. Reusing a volume that already contains data can leave stale files mixed with the migrated copy.
- Restore the tar archive into the destination volume from another short-lived helper container.
$ docker run --rm --mount source=notes-data,target=/to --mount type=bind,src=/srv/docker-backups,dst=/backup alpine tar -xzf /backup/notes-data.tar.gz -C /to
- Inspect the restored volume contents before attaching the application workload to it.
$ docker run --rm --mount source=notes-data,target=/data alpine ls -al /data total 20 drwxr-xr-x 3 root root 4096 Apr 16 08:49 . drwxr-xr-x 1 root root 4096 Apr 16 08:49 .. -rw-r--r-- 1 root root 14 Apr 16 08:49 app.sqlite -rw-r--r-- 1 root root 13 Apr 16 08:49 settings.ini drwxr-xr-x 2 root root 4096 Apr 16 08:49 uploads
Docker copies files from the container destination path into an empty volume by default when that volume is first mounted by a workload container. Restoring the archive before the application starts avoids mixing those seed files with migrated data, and the volume-nocopy mount option is available when an empty first mount must not copy image-side content.
- Attach the restored volume to the destination container or stack at the same container path used on the source host.
The application start command is workload-specific, but the mount path must stay the same or the restored data will not appear where the container expects it.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
