Docker Basics: How to Share Data Between a Docker Container and Host

2 Jul 2019 11:07am, by
The following post is the latest in a series of tutorials on using Docker and associated container tools. Check back every other week for a new edition.

With Docker containers, your company can offer applications and services on a scale and speed that you might not be able to otherwise. And since deploying containerized applications is so simple, you can get up to speed very quickly.

One thing you might soon discover (after taking your first few steps with Docker) is that, once deployed, your containers are limited in how they can save and contain data. The limitation lies within the container filesystem. Docker containers make use of the Union File System (UFS), which works with a series of read-only layers that includes a final read-write layer on top. This system functions perfectly when a container doesn’t need to save data. But when you need to deploy a service that requires the ability to save data (such as an application that works with a database), what do you do?

Welcome to Volumes

A Docker volume is a directory (or collection of files) that lives on the host file system and is not a part of the container’s UFS. It is within these volumes that containers are capable of saving data. With the docker volume command, you can easily manage volumes to expand your containers well beyond their basic capability.

Let’s find out how to deploy a new container that includes a volume attached to a specific directory on a host such that the container will stay in sync with the data in the volume. I’ll be demonstrating on Ubuntu Server 18.04, but the process will be the same (regardless of distribution) so long as the platform supports Docker. I will assume you already have Docker up and running and can deploy containers.

Creating the Host Data Volume

The first step is to create a new directory to house the volume. To do this, open a terminal window and issue the command:

You must ensure the newly-created directory is housed in a location the Docker user can access (with read-write privilege).

Once you’ve created that directory, you’re ready to mount a volume inside. Let’s say you’re going to deploy a container, based on the official Ubuntu image, that contains a directory called /data. To deploy such a container that attaches the internal /data directory to a volume within the host directory ~/container-data, you would issue the command:

The above command breaks down like this:

  • docker run is the main command that says we’re going to run a command in a new container.
  • -dit is d for detached mode, and it ensures that bash or sh can be allocated to a pseudo terminal.
  • -P publishes the containers ports to the host.
  • –name says what follows is the name of the new container.
  • -v says what follows is to be the volume.
  • ubuntu is the image to be used for the container.

Once the command completes, you will be given a container ID (Figure A). Make sure to remember the first four characters of that ID, as you’ll need it to gain access to the container bash prompt.

Our deployed container.

You’ve now deployed a container, based on the official Ubuntu image, that includes a /data directory which is mounted to the host volume in ~/container-data.

Testing the Volume

Let’s test this volume. If you’ve forgotten the ID of the container, issue the command docker ps -a to see it listed (Figure B).

Figure B: Our newly deployed container listing.

Access the newly-deployed container with the command:

Where ID is the first four characters of the deployed container. You should now find yourself at the bash prompt within the container (Figure C).

Figure C: The bash prompt of our new container.

Issue the command ls / and you will see the /data directory added to the Ubuntu container. Let’s create a test file in that directory with the command:

touch /data/test

After creating this test file, open another terminal window on the host machine and issue the command ls ~/container-data. You should see the test file within that directory (Figure D).

Figure D: Our test file, created from within the container, is seen within the volume on the host.

You’ve just deployed a container that includes persistent storage, via a volume on the host.

Database Volume

Let’s say you want to create a volume for a database. You can do this by first deploying a MySQL database Docker container and instructing it to use a persistent storage volume named mysql-data. Do this with the command:

In the above command, the -e switch informs docker what follows is an environment variable.

Access the bash prompt for the container with the command:

Where ID is the first four characters of the ID of the newly deployed container.

List out the contents of the container’s /var/lib/mysql directory with the command:

Make note of those contents and exit from the container with the command:

Now, check the contents of the host’s mounted volume with the command:

You should see the listing in both directories is the same (Figure E).

Figure E: Our MySQL data is in sync with the host volume.

You now have a MySQL-based container which includes persistent storage mounted in a volume on a host computer.

And that’s all there is to sharing data between a Docker container and a host. With volumes, this task is not only very easy, it’s also incredibly flexible.

The New Stack is a wholly owned subsidiary of Insight Partners, an investor in the following companies mentioned in this article: Docker.

Feature image by 200 Degrees from Pixabay.