You can work with two types of volumes in Docker:
Bind mounts: These are files or directories on the host system that are mounted into a Docker container. This means that any changes made to the volume from within the container will be reflected on the host filesystem, and vice versa. Files and folders are referenced by their absolute paths on the host machine.
Named volumes: Sometimes, this type of volume is called a Docker volume, or just a volume. Docker creates and manages named volumes to provide persistent storage for containers. They are not directly tied to the host machine.
Check out this 4sysops post to learn about named volumes in greater detail.
Here, we focus on moving a named volume from one host to another. For the purposes of demonstration, I will move a volume containing the custom images of my private docker registry from a source host (srv1) to a new host (srv2) running in Proxmox.
Back up a Docker volume
I will first ssh into my source Docker host (srv1) and view the custom Docker images stored in the private Docker registry. To do so, run the following commands:
sudo docker image ls curl -kL https://registry.testlab.local/v2/_catalog
As you can see in the screenshot, I have two custom Docker images (awesome_app and nginx). They are stored in a Docker volume (docker_repo). By the end of this tutorial, these images will reside on our new Docker host (srv2).
Backing up a bind mount is fairly easy, since it is just a directory on a Docker host. But to back up a Docker-managed volume, you first need to perform a few checks. First, run the following command to inspect the container you are going to back up (the container name in our case is registry).
sudo docker inspect registry
Once we know the name of the Docker volume, run the following command:
sudo docker run --rm \ --volumes-from registry \ --volume $(pwd):/docker_backup \ busybox tar -cvzf /docker_backup/registry.tgz docker_repo
The above command spins a temporary container with a busybox image, mounts the volumes of the registry container with the help of the --volumes-from option, mounts the current working directory from the host to the /docker_backup path in a temporary container, and finally, runs the tar command to compress the contents of the docker_repo volume. The --rm flag allows the container to clean itself once the tar command is successful. In a nutshell, this command creates a registry.tgz file in our current working directory on the source Docker host (srv1) containing all the files from the docker_repo volume.
We can now transfer this backup file to the target Docker host (srv2) using scp, as shown in the following command:
scp registry.tgz email@example.com:/home/surender/
Restoring a Docker volume
I will now ssh into the target Docker host. Let's first check whether the registry.tgz file, which we transferred from the other Docker host, is there. I will also verify that there is no existing volume named docker_repo.
Now, I run the following command to run a private Docker registry container on the new Docker host (srv2):
sudo docker run --detach \ --restart=always \ --name registry \ --mount type=volume,source=docker_repo,target=/docker_repo \ --env REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/docker_repo \ --publish 5000:5000 \ registry
I discussed this command in detail in my previous article. In a nutshell, this command creates a new local docker volume (docker_repo) and then launches a private Docker registry container with the docker_repo mounted volume.
I now have to change the A record of the registry.testlab.local subdomain to my new Docker host (srv2). At this stage, if we send a curl request to our private Docker registry, you will notice that there is no custom Docker image available yet.
ping registry.testlab.local curl -kL https://registry.testlab.local/v2/_catalog
To restore the volume that we backed up from the other Docker host (srv1), run the following command:
sudo docker run --rm \ --volumes-from registry \ --volume $(pwd):/docker_backup \ busybox sh -c "cd /docker_repo && tar -xvf /docker_backup/registry.tgz --strip 1"
This command launches a temporary container with a busybox image, uses the --volumes-from option to mount the registry container's volume (i.e., docker_repo), mounts the current working directory from the host to the /docker_backup path inside the container, and then runs the tar command to extract the registry.tgz file into the /docker_repo directory inside the container. In the end, we get all the contents extracted into the docker_repo volume on the new host, and the temporary container cleans itself once the extraction is finished.
Now repeat the curl command. This time, you will see two custom images (awesome_app and nginx) in response:
curl -kL https://registry.testlab.local/v2/_catalog
Since Docker-managed volumes are stored under the /var/lib/docker/volumes/ directory in Linux, run the following command to verify that everything was restored exactly where it is supposed to be:
sudo tree /var/lib/docker/volumes/docker_repo/ -L 7
You can now run the Docker pull command and start using your custom images from the private Docker registry running on the new host.
Subscribe to 4sysops newsletter!
sudo docker pull registry.testlab.local/awesome_app sudo docker image ls
That was all for this guide. You just learned how to move a Docker volume from one host to another.