By design, Docker containers do not store persistent data. Any data written to a container's writable layer will no longer be available once the container stops running. Also, getting data written to a container back out of it for another process can be difficult. To solve the issue of persisting data from a container, Docker has two options.

Matt McElreath

Matt McElreath is a Windows Server administrator concentrating on automation, PowerShell, Desired State Configuration (DSC), Octopus Deploy, and anything else thrown his way. You can follow Matt on Twitter at @mmcelreath.

Bind mounts: A bind mount is a file or folder stored anywhere on the container host filesystem, mounted into a running container. The main difference a bind mount has from a volume is that since it can exist anywhere on the host filesystem, processes outside of Docker can also modify it.

Volumes: Volumes are the preferred way to store persistent data Docker containers create or use. The host filesystem also stores volumes, similar to bind mounts. However, Docker completely manages them and stores them under C:\ProgramData\docker\volumes by default.

First, let's go over bind mounts. Let's say you want to make the c:\data folder on the container host machine available to a new container. This folder has the following text files:

Data folder to use as a bind mount

Data folder to use as a bind mount

We need to set a flag to mount that folder into the new container when running the docker run command.

Originally, the only way to mount a bind mount to a container was to use the -v or --volume flag to specify the location of the bind mount on the host filesystem and separate the path where to mount the file or folder inside the container with a colon. The command would look like this to start a new container with a bind mount to the data folder on the c:\ drive:

In this command, we are specifying -v followed by the location of the data folder on the container host (c:\data), then a colon, then the path inside the container where we want to mount this folder (c:\shareddata).

However, Docker 17.06 introduced the --mount flag for standalone containers. Docker recommends using the --mount flag in favor of -v because --mount is more explicit and easier to use. The same command to start a new container using a bind mount using --mount would look like this:

Notice the --mount flag uses key–value pairs separated by commas to specify the mount settings for this container, making it easier to see exactly what they're configuring. Also note that when using the ‑‑mount flag, the source folder must already exist on the container host. When using -v, if the directory does not exist, the command will create it automatically. If the directory does not exist when using ‑‑mount, Docker with throw an error.

Specifying -it in my docker run command will drop me into a PowerShell prompt on my running container. Running a directory listing on the C:\ drive within the new container shows that I have a folder called shareddata.

Directory listing showing the shareddata bind mount

Directory listing showing the shareddata bind mount

Now if I run a directory listing of the shareddata folder, we can see the same text files we saw on the container host.

Text files in the bind mount folder

Text files in the bind mount folder

Let's go ahead and hit Ctrl+PQ to exit this container while keeping it running in the background. Running docker ps shows that I now have one container running in the background. We will come back to this later.

Container with bind mount running in the background

Container with bind mount running in the background

Now let's take a look at volumes. Running docker volume will return some usage help for the available commands for managing volumes.

Docker volume command usage

Docker volume command usage

Let's start with creating a new volume. I'm going to go ahead and create one called logdata.

Now we can run docker volume ls to list the volumes currently available on this container host.

Docker volume listing

Docker volume listing

Similar to the bind mount, we can use the --mount flag to specify a volume to mount to a new container called volume1.

In this command, instead of specifying the path to a local directory in the source key, I'm specifying the name of the volume I want to mount to the container.

From inside my new container, I should now see a folder on the C:\ drive called logdata, which currently has no data in it.

Empty logdata volume mounted inside a new container

Empty logdata volume mounted inside a new container

Let's create a new file in the logfile directory called LogFile01.txt.

Creating a new file on the logfile volume

Creating a new file on the logfile volume

Now I'm going to hit Ctrl+PQ to exit this container while it is still running and use the same command to start up a new container called volume2. This will also mount the logdata volume to its own C:\ drive.

If we list the contents of the C:\logdata directory, we can see the text file we created from the volume1 container. Both volume1 and volume2 containers now have access to write to and read from the logdata volume.

Logdata directory on the volume2 container

Logdata directory on the volume2 container

Let's hit Ctrl+PQ again to bring us back to the container host.

Now I'm going to run docker inspect against a container named bindmount to look at how the bind mount's configuration data represents it.

Bind mount that docker inspect returns

Bind mount that docker inspect returns

Look for a section called Mounts. Now let's compare that to running docker inspect on the volume1 container.

Volume mount returned by docker inspect

Volume mount returned by docker inspect

You'll notice the source for both mounts contains a physical path to a directory on the container host filesystem. The difference is that Docker completely handles the volume's source. You don't need to know or manage its actual location.

Let's stop and remove all the running containers we created using the following Docker commands:

Now that we've stopped and removed the containers, we can go ahead and remove the logdata volume if we're done with it.

The final command I haven't covered yet is the prune command. Prune will remove all unused local volumes on the container host. This means it will remove from the system any volume not attached to a running or stopped container. You will obviously want to be careful with this command, so Docker will prompt you to confirm you are sure you want to continue.

Using the docker prune command

Using the docker prune command

Now that you've had an introduction to Docker volumes and bind mounts, feel free to explore more information about Docker storage on the Docker documentation site with Manage data in Docker.

Are you an IT pro? Apply for membership!

Share
3+

Users who have LIKED this post:

  • avatar

Related Posts

0 Comments

Leave a reply

Your email address will not be published. Required fields are marked *

*

CONTACT US

Please ask IT administration questions in the forum. Any other messages are welcome.

Sending
© 4sysops 2006 - 2018

Log in with your credentials

or    

Forgot your details?

Create Account