BoxBoat Blog

Service updates, customer stories, and tips and tricks for effective DevOps

x ?

Get Hands-On Experience with BoxBoat's Cloud Native Academy

Docker Data Containers and Named Volumes

by Will Kinard | Saturday, Jun 18, 2016 | Docker

featured.jpg

There are more than several informative blog posts and articles that explain Docker data management to great length, however confusion has recently been introduced with the introduction of the volume API in Docker 1.9. Managing persistent data within your containerized environment should not be difficult – thankfully with a little information, it’s not! There are recommended ways however to do it better that might set you up for less headache in the future. Let’s take a quick look at the what’s available to us now and what Docker recommends as the best path forward.

First, it also might help to catch up on Docker’s use of the union file system and why volumes are necessary in the first place. Images are a series of read-only layers that comprise that particular file system. A container is merely an instantiation of those read-only layers with a single read-write layer on top. In fact, the primary difference between an image and a container is the read-write layer. Any file changes that are made within a container are reflected as a copy of modified data from the read-only layer. The version in the read-write layer hides the underlying file, but does not remove it. When deleting a container, the read-write layer containing the changes are destroyed, and upon new container creation those changes are not reflected – gone forever! (If you’re interested in a more in-depth review, check out this webinar)

Intro Docker data volumes – the ability to persist data in an organized way outside of the container. A data volume is a specially-designated directory within one or more containers that bypasses the Union File System. Data volumes provide several useful features for persistent or shared data (from the Docker User Guide):

Data volumes are designed to persist data, independent of the container’s lifecycle. Docker therefore never automatically deletes volumes when you remove a container, nor will it “garbage collect” volumes that are no longer referenced by a container.

This is excellent functionality, but how do we take advantage of it? There are three ways to create volumes, with the last being the purpose of this post. We've created a short tutorial to show you docker volume create examples, and end with Docker named volumes.

1. Initialize (and mount) at run-time with the -v flag:

$ docker run -P --name web -v /webapp training/webapp python app.py

This will create a new volume inside a container at /webapp. Anything written to the /webapp directory will be persisted to the host machine, available to the next container that mounts it. But where is the actual volume stored? By using docker inspect, we can find where the it lives:

$ docker inspect -f {{.Mounts}} web

And you should see something like:

[{d87be9594b1ac6756c6069228e7b991deb1b8803a55dca23b0a3799c30dde05e /var/lib/docker/volumes/d87be9594b1ac6756c6069228e7b991deb1b8803a55dca23b0a3799c30dde05e/_data /webapp local  true }]

This “anonymous” volume was created at /var/lib/docker/volumes/d87…05e on my host machine. This isn’t exactly the most convenient for organization purposes…

2. Using the VOLUME instruction inside a Dockerfile:

FROM ubuntu:latest

VOLUME /webapp

This has the exact same effect as using the run flag above.

3. Create using the Docker Volume API introduced in Docker 1.9.

$ docker volume create --name webapp

This created a volume that I got to name and didn’t have to attach to anything right away. Seeing the flexibility here? More on this below.

There are other options to mount volumes including specifying host paths to mount directly within a container. Read up on these to become familiar with what’s available.

For a long time, the best practice for persisting data in Docker containers was using a well-defined paradigm of “data containers”, as documented in the Docker User Guide. In short, a container is created (but not necessary run) with a volume mounted using the top two methods above. When creating and running a container where persistent data storage is needed, the –volumes-from flag is used signifying to mount all volumes that are currently mounted to the container specified in the flag.

Here’s what this looks like in practice using persistent data in postgres as an example:

Create a data container (using the same image to save on disk space) with a mounted volume, /dbdata.

$ docker create -v /dbdata --name dbstore training/postgres /bin/true

Then use the –volumes-from flag to mount /dbdata in a new postgres container:

$ docker run -d --volumes-from dbstore --name db1 training/postgres

db1 now has a data volume mounted at /dbstore that it inherited from container dbstore.

What is this giving you that directly mounting a volume couldn’t do in the first place? Before Docker 1.9 and the inclusion of volume management, volumes couldn’t be named and were (and still are) known as anonymous volumes. Docker assigned a unique id under /var/lib/docker/volumes that was not easily managed by sight. By creating a container specifically for mounting volumes to, this created an organizational structure whereby the data container was named and easily referenced.

Introduced in Docker 1.9, named volumes provide better volume management as well as the ability to use other drivers for volume storage. They can be created as previously shown in option 3 above, but also using the same options you are familiar with:

$ docker run -P --name web -v webapp:/webapp training/webapp python app.py

Where “webapp” is the new named volume, mounted to /webapp in the container.

To create this named volume, execute the following command:

$ docker volume create webapp

To manage volumes have been created on your host, Docker provides a new Volume CLI, for example, to list all volumes:

$ docker volume ls
DRIVER              VOLUME NAME
local               dbdata

All volume commands available through –help flag:

Usage:  docker volume [OPTIONS] [COMMAND]

Manage Docker volumes

Commands:
    create                   Create a volume
    inspect                  Return low-level information on a volume
   ls                       List volumes
   rm                       Remove a volume

This new ability to manage and name volumes directly from the CLI truncates any further need for use of data containers. As seen in the docker github issue 17798, best practice is to use named volumes over data containers from here on out in most, if not all, use cases.

Now go out and try Docker named volumes to Deliver Software Faster!