Docker – The VOLUME instruction

Docker Compose Tutorial for Beginners

You should remember that a Docker image is made up of a series of read-only layers built upon one another, and that when you run a container from a Docker image, it creates a new read-write layer that you can think of as being on top of the read-only layers. All the changes to the container are applied to the read-write layer. If you make a change to a file found in one of the read-only layers, a copy of that file is made and added to the read-write layer. Then, all the changes are applied to the copy. The copy hides the version found in the read-only layer so, from the point of view of the running container, there is only one version of the file, and it is the one that has been changed. This is roughly how the Unified File System works. 

This is actually a great thing. However, it presents a challenge, this being that when the running container exits and is removed, all of the changes are removed with it. This is normally OK until you want to have some data that persists after the life of the container, or when you want to share data between containers. Docker has an instruction to help you solve this issue, the VOLUME instruction.

The VOLUME instruction will create a storage location that is outside of the United File System, and by so doing, allow storage to persist beyond the life of your container. Here is the syntax of the VOLUME instruction:

# VOLUME instruction syntax
VOLUME ["/data"]
# or for creating multiple volumes with a single instruction
VOLUME /var/log /var/db /moreData

Other ways to create volumes are to add volume parameters to the docker container run command or to use the docker volume create command. We will cover those methods in detail in Chapter 4, Docker Volumes.

Here is a simple example Dockerfile. It creates a volume at /myvol that will have a file named greeting:

# VOLUME instruction Dockerfile for Docker Quick Start
FROM alpine
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
CMD ["sh"]

Running a container based on an image made from this Dockerfile will create a mount point on the host system that initially contains the greeting file. When the container exits, the mount point will remain. Be careful with the use of the --rm parameter when running a container that has mount points you wish to persist. Using --rm, with no other volume parameters, will cause the mount points to be cleaned up along with the container when it exits. Here is what that looks like:

We start out with no volumes. Then, we run a container based on the image made from the preceding Dockerfile in detached mode. We check the volumes again, and we see the volume created by running the container. Then, we stop the container and check for volumes again, and the volume is now gone. Usually, the purpose of using a VOLUME instruction is to have data in a mount point that persists after the container is gone. So, if you are going to use --rm when you run a container, you should include the --mount run parameter, which we will cover in detail in Chapter 4, Docker Volumes.

You can interact with the data on the host using the mount point for a volume. Here is an example that demonstrates this:

In this demo, we run a container that is based on an image created with the preceding Dockerfile. Then, we list the volumes and see the myvolsrc volume (we already knew the name since we provided it in the run command, but you can use the ls command to find volume names that you might not otherwise know). Using the volume’s name, we inspect the volume to find its mount point on the host. To verify the contents of the volume in the container, we use an exec command to do an ls of the folder. Next, using the mount point path, we create a new file using the touch command. Finally, we use the same exec command and see that inside the container the volume has been changed (from actions outside of the container). Similarly, if the container makes changes to the contents of the volume, they are reflected instantly on the host mount point.

The preceding example will not work on OS X directly as shown. It requires some extra work. Don’t panic though! We’ll show you how to deal with the extra work required for OS X in Chapter 4, Docker Volumes.

Using the VOLUME instruction is both powerful and dangerous. It is powerful in that it lets you have data that will persist beyond the life of your containers. It is dangerous because data is passed instantaneously from the container to the host, and if the container is ever compromised, that can spell trouble. That is why, for security purposes, it is best practice to not include host-based VOLUME mounts in your Dockerfiles. We will cover some safer alternatives in Chapter 4, Docker Volumes.

The VOLUME instruction will add a zero-bytes sized layer to your resulting Docker image.

Comments are closed.