Understanding Docker volumes
One of the most common questions seen on Docker forums is how to separate data from containers. This is because any data created inside containers is lost when the container gets deleted. Using docker commit
to store data inside Docker images is not a good idea. To solve this problem, Docker provides an option called data volumes. Data volumes are special shared directories that can be used by one or more Docker containers. These volumes persist even when the container is deleted. These directories are created on the host file system, usually under the /var/lib/docker/
directory.
In this recipe, we will learn to use Docker volumes, share host directories with Docker containers, and learn basic backup and restore tricks that can be used with containers.
Getting ready
Make sure that you have the Docker daemon installed and running. We will need two or more containers.
You may need sudo
privileges to access the /var/lib/docker
directory.
How to do it…
Follow these steps to understand Docker volumes:
- To add a data volume to a container, use the
-v
flag with thedocker run
command, like so:$ docker run -dP -v /var/lib/mysql --name mysql\ -e MYSQL_ROOT_PASSWORD= passwdmysql:latest
This will create a new MySQL container with a volume created at
/var/lib/mysql
inside the container. If the directory already exists on the volume path, the volume will overlay the directory contents. - Once the container has been started, you can get the host-specific path of the volume with the
docker inspect
command. Look for theMounts
section in the output ofdocker inspect
:$ docker inspect mysql
- To mount a specific directory from the host system as a data volume, use the following syntax:
$ mkdir ~/mkdir $ docker run -dP -v ~/mysql:/var/lib/mysql \ --name mysql mysql:latest
This will create a new directory named
mysql
at the home path and mount it as a volume inside a container at/var/lib/mysql
. - To share a volume between multiple containers, you can use named volume containers.
First, create a container with a volume attached to it. The following command will create a container with its name set to
mysql
:$ docker run -dP -v /var/lib/mysql --name mysql\ -e MYSQL_ROOT_PASSWORD= passwd mysql:latest
- Now, create a new container using the volume exposed by the
mysql
container and list all the files available in the container:$ docker run --rm --volumes-from mysql ubuntu ls -l /var/lib/mysql
- To back up data from the
mysql
container, use the following command:$ docker run --rm--volumes-from mysql -v ~/backup:/backup \ $ tar cvf /backup/mysql.tar /var/lib/mysql
- Docker volumes are not deleted when containers are removed. To delete volumes along with a container, you need to use the
-v
flag with thedocker rm
command:$ dockerrm -v mysql
How it works…
Docker volumes are designed to provide persistent storage, separate from the containers' life cycles. Even if the container gets deleted, the volume still persists unless it's explicitly specified to delete the volume with the container. Volumes can be attached while creating a container using the docker create
or docker run
commands. Both commands support the -v
flag, which accepts volume arguments. You can add multiple volumes by repeatedly using the volume flag. Volumes can also be created in a Dockerfile using the VOLUME
instruction.
When the -v
flag is followed by a simple directory path, Docker creates a new directory inside a container as a data volume. This data volume will be mapped to a directory on the host filesystem under the /var/lib/docker
directory. Docker volumes are read-write enabled by default, but you can mark a volume to be read-only using the following syntax:
$ docker run -dP -v /var/lib/mysql:ro --name mysql mysql:latest
Once a container has been created, you can get the details of all the volumes used by it, as well as its host-specific path, with the docker inspect
command. The Mounts
section from the output of docker inspect
lists all volumes with their respective names and paths on the host system and path inside a container.
Rather than using a random location as a data volume, you can also specify a particular directory on the host to be used as a data volume. Add a host directory along with the volume argument, and Docker will map the volume to that directory:
$ docker run -dP -v ~/mysql:/var/lib/mysql \ --name mysql mysql:latest
In this case, /var/lib/mysql
from the container will be mapped to the mysql
directory located at the user's home address.
Need to share a single file from a host system with a container? Sure, Docker supports that too. Use docker run -v
and specify the file source on the host and destination inside the container. Check out following example command:
$ docker run --rmd -v ~/.bash_history:/.bash_history ubuntu
The other option is to create a named data volume container or data-only container. You can create a named container with attached volumes and then use those volumes inside other containers using the docker run --volumes-from
command. The data volumes container need not be running to access volumes attached to it. These volumes can be shared by multiple containers, plus you can create temporary, throwaway application containers by separating persistent data storage. Even if you delete a temporary container using a named volume, your data is still safe with a volume container.
From Docker version 1.9 onwards, a separate command, docker volume
, is available to manage volumes. With this update, you can create and manage volumes separately from containers. Docker volumes support various backend drivers, including AUFS, OverlayFS, BtrFS, and ZFS. A simple command to create a new volume will be as follows:
$ docker volume create --name=myvolume $ docker run -v myvolume:/opt alpine sh
See also
- The Docker volumes guide: http://docs.docker.com/engine/userguide/dockervolumes/
- Clean up orphaned volumes with this script: https://github.com/chadoe/docker-cleanup-volumes