Docker Volume

Docker containers data is volatile. If we create any file in /tmp folder and by mistake if we delete the container, that file and directory will also be deleted. But suppose we are working in a prod environment and then if we face such a situation then your crucial data might be deleted.

To make docker data persistent we have docker volumes are the preferred mechanism for persisting data generated by and used by Docker containers.

In docker, there are two ways to achieve persistent data

  1. Using volumes
  2. Using bind mounts

Using Volumes

First let's list the images available-

gaurav@learning-ocean:~$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
mysql        latest    c60d96bd2b77   11 days ago    514MB
ubuntu       14.04     13b66b487594   4 months ago   197MB
gaurav@learning-ocean:~$

Inspect the mysql image-

gaurav@learning-ocean:~$ docker image inspect mysql

In the output, check out for volumes and here what I have -

gaurav@learning-ocean:~$ docker image inspect mysql
[
    {
       # output removed
            "Volumes": {
                "/var/lib/mysql": {}
            },
      # output removed
    }
]

This means that docker will mount the volume at this location.

Create a container from MySQL image and list the volumes -

gaurav@learning-ocean:~$ docker volume ls
gaurav@learning-ocean:~$ docker container run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
2a7aadab7cf6bda9fdc35810227517eaa5e97d2cdedfbe7e1583c028a37a3566
gaurav@learning-ocean:~$ docker volume ls
DRIVER    VOLUME NAME
local     997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395
gaurav@learning-ocean:~$

Here the volume with id starting 997 has been created at the location - /var/lib/mysql

Now let's inspect the volume itself -

gaurav@learning-ocean:~$ docker volume inspect 997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395
[
    {
        "CreatedAt": "2021-08-02T16:08:35Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395/_data",
        "Name": "997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395",
        "Options": null,
        "Scope": "local"
    }
]
gaurav@learning-ocean:~$

The mount point is where you will find the volume minted on the docker host -

gaurav@learning-ocean:~$ sudo su
[sudo] password for gaurav:
root@learning-ocean:/home/gaurav# cd /var/lib/docker/volumes/997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395/_data/
root@learning-ocean:/var/lib/docker/volumes/997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395/_data# ls
 auto.cnf          client-key.pem       ibtmp1               server-cert.pem
 binlog.000001    '#ib_16384_0.dblwr'  '#innodb_temp'        server-key.pem
 binlog.000002    '#ib_16384_1.dblwr'   mysql                sys
 binlog.index      ib_buffer_pool       mysql.ibd            undo_001
 ca-key.pem        ibdata1              performance_schema   undo_002
 ca.pem            ib_logfile0          private_key.pem
 client-cert.pem   ib_logfile1          public_key.pem
root@learning-ocean:/var/lib/docker/volumes/997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395/_data# exit

Now I will go inside the container and create a few mysql databases and then remove the container-

gaurav@learning-ocean:~$ docker container exec -it 2a7 bash
root@2a7aadab7cf6:/# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.26 MySQL Community Server - GPL
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)


mysql> create database learingocean;
Query OK, 1 row affected (0.01 sec)
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> create database example;
Query OK, 1 row affected (0.01 sec)
mysql> exit
Bye
root@2a7aadab7cf6:/# exit
exit
gaurav@learning-ocean:~$

Now, let's remove the container-

gaurav@learning-ocean:~$ docker container rm -f 2a
2a

Create a new container again -

gaurav@learning-ocean:~$ docker container run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
1fec03b43712be52967713d2f9f9f8d367a6926faccbb206fa07c4bcbcb13deb
gaurav@learning-ocean:~$ docker container exec -it 1f bash
root@1fec03b43712:/#

And check the databases -

root@1fec03b43712:/# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.26 MySQL Community Server - GPL
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)
mysql>

None of the databases we created and all the data is lost.

We can also create a new container with pre-populated data or say the existing volume. Let's see how we create a new container with already existing volume -

We have these volumes as of now -

gaurav@learning-ocean:~$ docker volume ls
DRIVER    VOLUME NAME
local     997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395
local     f64908bbe87a99d487b35110c6335e63e5e91fc174088e610c87571d32c160f9
gaurav@learning-ocean:~$

Now to create a container with the volume id 997 already mounted on it, run the below command -

gaurav@learning-ocean:~$ docker container run -itd -v 997a7e220305eb30a9307c686648f9417f06509e0c9ce28cc4fc2028c513b395:/var/lib/mysql mysql
a9b9f511d66571b993fa2084de0a2f2dfafab416017c1d2081d8f9ccbc035c46

Verifying the same-

gaurav@learning-ocean:~$ docker container exec -it a9 bash
root@a9b9f511d665:/# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.26 MySQL Community Server - GPL
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| example            |
| information_schema |
| learingocean       |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
7 rows in set (0.01 sec)
mysql>