Linux:Powerful Server Administration
上QQ阅读APP看书,第一时间看更新

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:

  1. To add a data volume to a container, use the -v flag with the docker 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.

  2. Once the container has been started, you can get the host-specific path of the volume with the docker inspect command. Look for the Mounts section in the output of docker inspect:
    $ docker inspect mysql
    
  3. 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.

  4. 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
    
  5. 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
    
  6. 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
    
  7. Docker volumes are not deleted when containers are removed. To delete volumes along with a container, you need to use the -v flag with the docker 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