Understanding Docker Volumes

Understanding Docker Volumes

Let us understand data persistence in Dockers using examples to create, backup, migrate, and restore Docker Volumes.

Docker overview

Docker is an open platform for developing, shipping, and running your applications. It enables you to separate your applications from their infrastructure so you can deliver the software quicker than ever before. With Docker, you can manage the infrastructure of your app the same way you manage your applications which makes the entire process quite streamlined for developers. By using Docker’s methodologies for shipping, testing, and deploying code quickly, developers can reduce the delay between writing code and running it in production. This helps make the entire process both cost and time effective.

In simpler words, Docker is a tool designed to make it easier to create, deploy, and run applications with the help of containers. Containers allow a developer to wrap an application along with required components like libraries and other dependencies before shipping it all out as one package.

What are Docker Volumes?

Volumes are the preferred, and extensively used, mechanisms for persisting data generated by Docker containers. Docker volumes basically create a link between one of the local folders on the system and the folder on the docker container. These folders have data replication so that even if a container gets restarted/deleted at some point in time, you will still have access to the data that the container generated.

Volume Drivers let you store volumes on remote hosts or cloud providers. They are used to encrypt the contents of volumes or to add other functionalities. Using volume drivers, new volumes can have their content pre-populated by a container.

Docker volumes also facilitate data sharing between containers.

About this article

In this article we try to understand the concept of docker volumes by taking a few examples and implementing the same in this demo project.

So let’s get started!

Linking the host file system to the docker container virtual file system

Here, we will create a host folder/file, link it to the docker container folder, and test scenarios out to see how this works.

  • First create a folder on your local system which will persist container folder data. Here, it is $(pwd)/docker/docker_vol in our demo example. Now run the following code snippet:
docker run --name volnginx -v <absolute_path>/docker/docker-vol/:/usr/share/nginx/html -p 8080:80 -d nginx

--name => name of the running container

-v => mounts volume/links /docker/docker-vol/ to /usr/share/nginx/html

-p => publish the container's port(80) to the host(8080)

-d => runs docker container in background in detached mode.

This will the link the two file systems.

As this is a nginx container, let's add our own static content to it.

docker_vol/index.html (on host):

Hello this is index.html

docker_vol/hello.html (on host):

Hello this is hello.html

Log into the container and view the shared file/folder content

docker exec -it volnginx /bin/bash
ls /usr/share/nginx/html

Screenshot 2022-03-30 at 7.16.35 AM.png

Now, view localhost:8080 and localhost:8080/hello.html.

Screenshot 2022-03-30 at 7.20.21 AM.png

Screenshot 2022-03-30 at 7.20.42 AM.png

Remove hello.html from host system. localhost:8080/hello.html will have no content to show.

Now, let's create a file from inside the docker container in the same shared folder. The same file will now be persisted on the host folder.

Screenshot 2022-03-30 at 7.26.36 AM.png

To provide the container only read-only permissions on the folder:

docker run --name volnginx -v <absolute_path>/docker/docker-vol/:/usr/share/nginx/html:ro -p 8080:80 -d nginx

This is an example of Mount Type: bind where we mount an existing file system to docker container.

This can be done as follows:

docker inspect volnginx

and view under the Mount object

...
"Mounts": [
            {
                "Type": "bind",
                "Source": "<directory>/docker-vol/",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ]
...

Creating named Docker Volume

If you don't want to create a directory or have an existing directory to work with, you can simply create a volume and attach it the container as follows:

docker volume create hello
docker run --name mynginx1 -v hello:/<directory inside the container>:ro  -p 8080:80 -d <image>

Here, we create a volume called hello and simply attach it to run an instance of the image(here we use nginx again).

The directory of the image will be created on the following location:

/var/lib/docker/volumes/<vol_name>/_data

As previous example, we can go ahead and make changes to this directory and the same will be reflected in the file system of the container.

This is an example of Mount Type: volume type.

docker inspect mynginx1

show the following Mount object -

...

"Mounts": [
            {
                "Type": "volume",
                "Name": "hello",
                "Source": "/var/lib/docker/volumes/hello/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "ro",
                "RW": false,
                "Propagation": ""
            }
        ]
...

Note: The directory the docker volume creates can easily be located in Linux systems.

Sharing Docker Volumes across Containers

This section is relatively easy as you can simply attach a single volume to a number of containers and thus, enable sharing of data between them.

docker run --name mynginx1 -v hello:/<directory inside the container>:ro  -p 8080:80 -d <image>
docker run --name mynginx2 -v hello:/<directory inside the container>:ro  -p 8081:80 -d <image>

These launched containers will use the same volumes.

If there are a number of volumes attached to the container and we require all the volumes from that container to be attached to a new one, we can simply use the following code:

docker run --name mynginx3 --volumes-from mynginx1 -p 8082:80 -d nginx

Backup, Restore, and Migration of Docker Volumes

Backup

  • The contents of existing volume (hello) -
    ls -la /var/lib/docker/volumes/hello/_data/
    

Screenshot 2022-04-03 at 1.46.43 PM.png

  • We create a backup directory

  • We share the existing volume into a new container along with the backup directory.

  • We create a compressed version of the existing/shared volume inside the backup container of the directory.

  • Thus making a copy of the compressed form onto the host system.

  • Finally, remove the new container after the work is done using (--rm).

mkdir ~/backup
docker run --rm --volumes-from mynginx1 -v ~/backup:/backup ubuntu bash -c "cd /usr/share/nginx/html && tar cvf /backup/container.tar ."

The content of ~/backup is container.tar.

Restore

Let us now the restore the contents into a new Docker Volume.

  • We follow a similar command as above.

    docker run --rm -v newvol:/recover -v ~/backup:/backup ubuntu bash -c "cd /recover && tar xvf /backup/container.tar"
    
  • To view the contents of the newly created volume -

ls -la /var/lib/docker/volumes/newvol/_data/

Screenshot 2022-04-03 at 1.48.50 PM.png

Migrate

The created compressed folder can be transferred onto a different host via any file transferring mechanism like scp, rsync, etc. and can be restored there.

Using Volumes in Docker Compose

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, we use a YAML file to configure our application’s services. Then, with a single command, you create and start all the services from your configuration.

We can implement and define Volumes in docker-compse.yaml in a very basic way as follows:

version: '3.5'

services:
  corporate:
    image: corporate.thetopgeek:latest
    volumes:
      - <host_path>:<conatiner_path>            ## for host-mounted volumes
      - <named_volume>:<container path>         ## for named volumes

Advantages of Docker Volumes

  • Docker volumes provide a great way to persist data.

  • The learning curve is not that steep.

  • Managing volumes can done from the Docker CLI or Docker API.

  • They are easy to backup, restore, and migrate.

  • Sharing data among containers is relatively simpler.

Hope this article helps setup Docker Volume and interests you to use it in your Docker environment and infrastructure.

Thank you and keep enjoying Docker !!🐳 😀

This is a part of a series of articles to help understand Docker better. Find the other articles as follows: