• Get In Touch
May 30, 2016

Working with Docker Volumes

Need Hosting? Try ours, it's fast, reliable and feature loaded with support you can depend on.
View Plans

Introduction

One of the most common questions for people using Docker is the use of volumes. In order to understand what is a docker volume? First, you will need to know how docker filesystem works. Docker images are stored as a series of read-only layers. When we start a container, Docker takes the read-only image and adds a read-write layer on top. By default docker filesystems are temporary union filesystems. You can pull a docker image, start a container, create, modify and delete files in docker system. But if you stop container and start it up again, all your changes will be lost. In this situation a docker volume will be used to retain your data in volumes.

When a Docker container is deleted, relaunching the image will start a fresh container without any of the changes made in the previously running container and those changes are lost. Docker calls this combination of read-only layers with a read-write layer on top a Union File System.

The Docker volume is a directory that is located outside of the root filesystem of your container. This allows you to import this directory in other container’s and use volumes to mount directories from your host machine inside a container.

It also permits data to be stored in a container outside of the boot volume.
There are two ways to manage data in Docker –

  1. Docker Data Volumes

A data volume is a directory within a container that persists beyond the life cycle of the container. All volumes are stored on the Docker host in a system path. It can be shared and reused among containers.

  1. Docker Data Volume Containers

A data volume container is a container that houses a volume and used to store data in a persistent way. Because volumes can be shared with other containers and used as a centralised data store across multiple containers on the same Docker host. You can also mount other containers volume inside a data volume container and save their data to it.

In this tutorial, we will learn the concept of the docker volume, types of volume and how effectively data volumes can be used to share data between the Docker host and the containers as well as between containers.

Requirements

Ubuntu server 14.04 with docker installed on your system.

Features of Data Volume

A data volume is a specially designated directory within one or more containers that bypasses the Union File System.

Docker data volumes provide several useful features, some of them are listed below:

  1. Data volumes can be shared and reused among containers.
  2. Data volumes can be used to share data between the host filesystem and the Docker container.
  3. You can directly change a data volume, changes to a data volume will not be included when you update an image.
  4. Data volumes persist, even if container is restarted or deleted.
  5. Data can be backed up, restored, and migrated more easily.
  6. You don’t need to manually specify host mount points and handle the additional concerns of file permissions and security restrictions.

Creating and Mounting Data Volume

You can not create data volumes directly in Docker. First, you will need to create a data volume container with a volume attached to it.

You can use docker create command to create the data volume container.

Now, first create a new data volume container to store your volume by using the following command:

sudo docker create -v /mnt --name data_volume_container ubuntu

This will create a new data volume container named data_volume_container from the ubuntu base image in the directory /mnt

You can use docker ps -a command to list data volume container created above:

sudo docker ps -a

You should see the following output:

    4522bd3ec0da        ubuntu                 "/bin/bash"              33 minutes ago      Created                                         data_volume_container
    534544f2e924        centos                 "/bin/bash"              3 weeks ago         Exited (137) 3 weeks ago                        boring_hamilton
    6c31f7ad39a7        dockerui/dockerui      "/dockerui /bin/bash"    5 weeks ago         Exited (2) 5 weeks ago                          amazing_meitner
    0925473d7dd2        dockerui/dockerui      "/dockerui"              5 weeks ago         Exited (2) 5 weeks ago                          tender_boyd
    d25b0a968294        dockerui/dockerui      "/dockerui"              5 weeks ago         Exited (2) 5 weeks ago                          suspicious_ptolemy
    e919b224e52d        ubuntu                 "/bin/bash"              8 weeks ago         Exited (0) 2 weeks ago                          lonely_poincare
    573197038ed1        apache                 "/usr/sbin/apache2ctl"   8 weeks ago         Exited (143) 8 weeks ago                        Apache-Instance
    f49877210e7d        ubuntu:Apache_Server   "/usr/sbin/apache2ctl"   9 weeks ago         Exited (143) 9 weeks ago                        Apache_Instance

Next, you will need to run Ubuntu container with the --volumes-from flag. After this anything you write to the /mnt directory will get saved to
the /mnt volume of your data_volume_container container.

Let’s run the following command with --volumes-from flag:

sudo docker run -t -i --volumes-from data_volume_container ubuntu /bin/bash

Now, check the mount details by runningng the following command in container shell:

mount

You should see the following output:

    none on / type aufs (rw,relatime,si=8b6ea26c8dbb142d,dio)
    proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
    tmpfs on /dev type tmpfs (rw,nosuid,mode=755)
    devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
    sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
    tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,relatime,mode=755)
    cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)
    cgroup on /sys/fs/cgroup/cpu type cgroup (ro,nosuid,nodev,noexec,relatime,cpu)
    cgroup on /sys/fs/cgroup/cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpuacct)
    cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)
    cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
    cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)
    cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)
    cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)
    cgroup on /sys/fs/cgroup/hugetlb type cgroup (ro,nosuid,nodev,noexec,relatime,hugetlb)
    systemd on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,name=systemd)
    /dev/disk/by-uuid/6425dd49-3030-4430-b695-8fffb6779f62 on /mnt type ext4 (rw,relatime,errors=remount-ro,data=ordered)
    /dev/disk/by-uuid/6425dd49-3030-4430-b695-8fffb6779f62 on /etc/resolv.conf type ext4 (rw,relatime,errors=remount-ro,data=ordered)
    /dev/disk/by-uuid/6425dd49-3030-4430-b695-8fffb6779f62 on /etc/hostname type ext4 (rw,relatime,errors=remount-ro,data=ordered)
    /dev/disk/by-uuid/6425dd49-3030-4430-b695-8fffb6779f62 on /etc/hosts type ext4 (rw,relatime,errors=remount-ro,data=ordered)
    shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
    mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
    devpts on /dev/console type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
    proc on /proc/asound type proc (ro,nosuid,nodev,noexec,relatime)
    proc on /proc/bus type proc (ro,nosuid,nodev,noexec,relatime)
    proc on /proc/fs type proc (ro,nosuid,nodev,noexec,relatime)
    proc on /proc/irq type proc (ro,nosuid,nodev,noexec,relatime)
    proc on /proc/sys type proc (ro,nosuid,nodev,noexec,relatime)
    proc on /proc/sysrq-trigger type proc (ro,nosuid,nodev,noexec,relatime)
    tmpfs on /proc/kcore type tmpfs (rw,nosuid,mode=755)
    tmpfs on /proc/latency_stats type tmpfs (rw,nosuid,mode=755)
    tmpfs on /proc/timer_stats type tmpfs (rw,nosuid,mode=755)

You should see the mountpoint /mnt in above output.

Next, create a file named volume.txt in /mnt directory of Ubuntu container to test whether data volume working or not:

echo "Testing Docker volume" > /mnt/volume.txt

Next, run the exit command to return to your host machine’s shell:

exit

Next, run the same command again:

sudo docker run -t -i --volumes-from data_volume_container ubuntu /bin/bash

You should see the volume.txt file already there.

cat /mnt/volume.txt

You should see:

    Testing Docker volume

You can use the -v multiple times to mount multiple data volumes and also use the VOLUME instruction in a Dockerfile to add one or more new volumes to any container created from that image.

Locating a Data Volume

You can locate the volume on the host by running the docker inspect command. This command provides details on the container configurations, including the volumes.

sudo docker inspect data_volume_container

The output should look something similar to the following:

    "Mounts": [
                {
                    "Name": "ae26fc614c8dbf12c55a56ab0a0c1d2c2c0c4dcc9d070832969e9761b46d7330",
                    "Source": "/var/lib/docker/volumes/ae26fc614c8dbf12c55a56ab0a0c1d2c2c0c4dcc9d070832969e9761b46d7330/_data",
                    "Destination": "/mnt",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                }
            ],

Here, the data volume is mapped to a directory in the Docker host, and the directory is mounted in read-write mode. This directory is created by the
Docker engine automatically during the container launch time. In the above output, source specifies the location on the docker host system, destination specifies the volume location inside the container and RW shows if the volume is read/write.

Sharing Data Between Containers

In this section, we will create a data volume container. This is very useful if you want to share data between containers or you want to use the data from non-persistent containers.

First, create a container named volume_container1 and mount a volume named data inside it.

You can do this by running the following command:

sudo docker run -it -v /data --name volume_container1 ubuntu

Now, go into the /data volume and create some files inside it for testing purposes.

cd /data
echo "Testing Data Volume Container" > file1
echo "Testing Data Volume Container" > file2

Now press Ctrl-P-Q to come back to the Docker host system without exiting the container.

Next, run docker ps command on the Docker host system:

sudo docker ps

You should see your running container:

    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    d0d7d4e3d466        ubuntu              "/bin/bash"         6 minutes ago       Up 6 minutes                            volume_container1

Now, execute a command on the running volume_container1 and see the contents of /data volume:

sudo docker exec volume_container1 ls /data

    file1
    file2

You can see that the two files are present.

Now, launch another container volume_container2 and mount the data volume from volume_container1.

You can do this by running the following command:

sudo docker run -it --volumes-from volume_container1 --name volume_container2 ubuntu

Next, run ls command inside volume_container2, you should see that data folder is present with two files file1 and file2 inside the data folder.

ls

    bin  boot  data  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var


    `cd data`
    `ls`


    file1
    file2

Mount a Host file as a Data Volume

You can also mount a single file instead of directories from the host system:

For example, to mount /var/log/dmesg file as a data volume from the Docker host system, run the following command:

sudo docker run --rm -it -v /var/log/dmesg:/var/log/dmesg ubuntu /bin/-bash

This will drop you into a bash shell in a new container, you will have your dmesg log from the host system and when you exit the container, the host will have the dmesg log of the container.

Backup and Restore Data Volumes

Another important function you can perform with docker volumes is to use them for backup and restore. To backup a data volume you can run a new container using the volume you want to backup and executing the tar command to produce an archive of the volume content .

You can do this by using the --volumes-from flag to create a new container that mounts that volume:

To backup data_volume_container run the following command:

sudo docker run --rm --volumes-from data_volume_container -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /mnt

--volumes-from flag creates a new nameless container that mounts the data volume inside data_volume_container you wish to backup.

A localhost directory is mounted as /backup . Then tar archives the contents of the /mnt volume to a backup.tar file inside the local /backup directory.

The container will be --rm removed once it ends and exits

You can also restore the volume in whatever way you wish.

To restore the volume into new container data_volume_container1, run the following command on Docker host system:

sudo docker run -v /mnt --name data_volume_container1 ubuntu /bin/bash

Next, extract the backup.tar file into the new container’s data volume by running the following command:

sudo docker run --rm --volumes-from data_volume_container1 -v $(pwd):/backup ubuntu bash -c "cd /mnt && tar -zxvf /backup/backup.tar"

Now the new container is up and running with the files from the original /mnt volume.

Removing Volumes

A Docker data volume persists after a container is deleted. When a container is removed using the docker rm subcommand, the Docker engine does not remove the directory that was automatically created during the container launch time. This behavior is designed to preserve the state of the containers application that was stored in the directory. If you want to remove the directory that was automatically created by the Docker engine, you can do so while removing the
container by providing a -v option to the docker rm subcommand, on an already stopped container:

Run the following command to delete container with volume:

sudo docker rm -v "container_id"

If the container is still running, then you can remove the container as well as the
auto-generated directory by adding a -f option to the previous command:

sudo docker rm -fv "container_id"

Conclusion

In this tutorial you have learned how docker volumes work, sharing data between container to container as well as between the Docker host to container. Data sharing using data volumes is turning out to be a very powerful and essential tool in the Docker.

Need Hosting? Try ours, it's fast, reliable and feature loaded with support you can depend on.
View Plans

Share this Article!

Related Posts

Node.js Authentication – A Complete Guide with Passport and JWT

Node.js Authentication – A Complete Guide with Passport and JWT

Truth be told, it’s difficult for a web application that doesn’t have some kind of identification, even if you don’t see it as a security measure in and of itself. The Internet is a kind of lawless land, and even on free services like Google’s, authentication ensures that abuses will be avoided or at least […]

Node.js and MongoDB: How to Connect MongoDB With Node

Node.js and MongoDB: How to Connect MongoDB With Node

MongoDB is a document-oriented NoSQL database, which was born in 2007 in California as a service to be used within a larger project, but which soon became an independent and open-source product. It stores documents in JSON, a format based on JavaScript and simpler than XML, but still with good expressiveness. It is the dominant […]

Using MySQL with Node.js: A Complete Tutorial

Using MySQL with Node.js: A Complete Tutorial

Although data persistence is almost always a fundamental element of applications, Node.js has no native integration with databases. Everything is delegated to third-party libraries to be included manually, in addition to the standard APIs. Although MongoDB and other non-relational databases are the most common choice with Node because if you need to scale an application, […]

Node.Js Vs Django: Which Is the Best for Your Project

Node.Js Vs Django: Which Is the Best for Your Project

Django and NodeJs are two powerful technologies for web development, both have great functionality, versatile applications, and a great user interface. Both are open source and can be used for free. But which one fits your project best? NodeJs is based on JavaScript, while Django is written in Python. These are two equally popular technologies […]

Nodejs Vs PHP:  Which Works Best?

Nodejs Vs PHP: Which Works Best?

Before getting into the “battle” between Node.js and PHP we need to understand why the issue is still ongoing. It all started with the increased demand for smartphone applications, their success forcing developers to adapt to new back-end technologies that could handle a multitude of simultaneous requests. JavaScript has always been identified as a client-side […]