DevOps

Docker Volumes Example

Each Docker container stores the data its processes need in that container. Unless we make the container store the data outside the container, which is extremely useful for when we don’t want to have the data layer we work with tied to the running container. That’s what we are going to see in this example, using Docker volumes.

For this tutorial, Linux Mint 18 and Docker version 1.12.3 have been used.
 
 
 
 
 
 

Tip
You may skip Docker installation and jump directly to the beginning of the example below.

1. Installation

Note: Docker requires a 64-bit system with a kernel version equal or higher to 3.10.

We can install Docker simply via apt-get, without the need of adding any repository, just installing the docker.io package:

sudo apt-get update
sudo apt-get install docker.io

For more details, you can follow the Install Docker on Ubuntu Tutorial.

2. Understanding volumes

The containers, apart from the running services, also store all the data within it. This means that, if we remove the container, all the data that has been added or changed will be gone.

For some cases this might be fine, but for others, we may want to make the data persist outside the container. The clearest example can be a container running a database, for which perhaps we don’t want to store the data in the container where the database service is running, but in the file system of the host. Another use, for example, can be for sharing data among several containers.

Docker allows this using a concept named as “Data volumes”. Actually, is very simple: a volume is a file or directory that is mounted directly in the container. The concept is the same as the “mount” in Linux.

3. Mounting a directory from the host to the container

As we used databases as example for the brief explanation for Docker volumes, why not using one for our example?

Before anything, let’s create the directory that will be binded to the MySQL data directory, for example:

mkdir -p $(echo $HOME)/docker/mysql-data

If you are using an existing one, take into account that MySQL needs an empty directory for storing its data.

Now, let’s pull the MySQL image; it’s enough to pull the default tagged one:

docker pull mysql

For using data volumes, the difference comes when creating the container. For indicating to Docker that we are going to use a volume, we have to use the -v (--volume) option, with the following format:

docker run -v /host/path:/container/path

By default, MySQL stores its data in /var/lib/mysql, so that’s the directory we have to bind:

docker run -d \
           --name=mysql1 \
           -v $(echo $HOME)/docker/mysql-data:/var/lib/mysql \
           -e MYSQL_ROOT_PASSWORD=test \
           mysql

(Note that we also passed a password for MySQL root user in the environmental variable MYSQL_ROOT_PASSWORD).

We can check the volumes information, among other things, with the inspect command. As the output is quite long, we can format it to just show the volumes information:

docker inspect --format '{{ index .Mounts }}' mysql1

Which, in my case, shows:

[{ /home/julen/docker/mysql-data /var/lib/mysql   true rprivate}]

Returning to the container. now, host’s $HOME/docker/mysql-data is mounted to container’s /var/lib/mysql. If we now list the directory of the directory, we will see that there are several files and directories, which have been created by MySQL.

Let’s now make a little test to see that our data persistence is working, and that the data used in the container, is actually not dependent of it. For this, we will create a database with a table, and insert a row:

docker exec -it mysql1 /bin/bash
mysql -u root -p

After entering the password we set and being in the MySQL console, we will create the database and the table, and some data:

CREATE DATABASE testdb;
USE testdb;
CREATE TABLE test(foo varchar(100));
INSERT INTO test VALUES('a value');

Let’s remove now the container:

docker rm -f mysql1

And, create another one, of course, mounting the data directory:

docker run -d \
           --name=mysql2 \
           -v $(echo $HOME)/docker/mysql-data:/var/lib/mysql \
           -e MYSQL_ROOT_PASSWORD=test \
           mysql

If we connect now to the database of this container, with the same commands as above (just replacing mysql1 with mysql2, for the container name), we will see that the database already exists, and that the introduced data is still there:

USE testdb;
SELECT * FROM test;

The output would be:

+---------+
| foo     |
+---------+
| a value |
+---------+
1 row in set (0.00 sec)

4. Summary

This example has shown how to use Docker volumes, which are really useful when we want to keep the data separated from the actual container. We have seen how does it work by creating a container with a database, deleting the container, creating another new one, and seeing how the created data persisted.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button