WittCode💻

Docker Volumes Explained

By

Learn about docker volumes including named docker volumes, anonymous docker volumes, and how to remove, list, and create docker volumes.

Table of Contents 📖

What is a Docker Volume?

Docker volumes are a feature of Docker that maps file systems on a host machine to file systems on a Docker container. This allows for data to persist longer than the lifecycle of the container. When a Docker container is removed, all data changes inside the Docker container are lost. This is bad if we have data changes that we want to be persisted in the container, such as database data. With Docker volumes, if the docker container is removed, the data changes will not be lost as they will be taken from the host.

Creating Docker Volumes

Docker volumes can be created with the command docker volume create <volume_name>. Lets create a volume called my_volume.

docker volume create my_volume

We can create an anonymous docker volume (a volume without a name) by omitting the volume name. This command returns the name of the volume that docker created.

docker volume create 2f2da4fbfdb2c1127b3777782b897a7d31fadc3a3af5364e283057b1c59e3d58

When a volume is created, Docker creates a directory for it under /var/lib/docker/volume/<volume_name>. The volume my_volume is now present in this directory along with the volume docker created.

Listing Docker Volumes

We can then list the docker volumes present by running the command docker volume list.

docker volume list DRIVER VOLUME_NAME local my_volume local 2f2da4fbfdb2c1127b3777782b897a7d31fadc3a3af5364e283057b1c59e3d58

The DRIVER column is the location of the volume and VOLUME_NAME is the name of the volume. We can get more information about the volume by using the docker volume inspect <volume_name> command. Lets inspect our my_volume volume.

docker volume inspect my_volume [ { "CreatedAt": "2022-11-01T02:55:24+01:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/my_volume/_data", "Name": "my_volume", "Options": {}, "Scope": "local" } ]

Now we can see more information such as when the volume was created and also its mountpoint which is its location on the host machine. As stated previously, this is inside /var/lib/docker/volume.

Deleting Docker Volumes

We can remove Docker volumes with the docker volume rm <volume_name> command.

docker volume rm 2f2da4fbfdb2c1127b3777782b897a7d31fadc3a3af5364e283057b1c59e3d58 2f2da4fbfdb2c1127b3777782b897a7d31fadc3a3af5364e283057b1c59e3d58

What is returned is the name of the volume that was removed. We can remove all unused volumes (volumes not currently being used by a container) with the docker volume prune command.

docker volume prune WARNING! This will remove all local volumes not used by at least one container. Are you sure you want to continue? [y/N] y Deleted Volumes: my_volume

Starting a Container with a Volume

We can start a container using a volume by supplying the docker run command the --volume argument with the volume name, a colon, and then a mount point within the container.

docker run --volume my_volume:/var/lib/postgresql/data

This is known as a named docker volume as we provided the name of the volume (my_volume). This is the type of Docker volume that should be used in production. This is also essentially the same as when we created a docker volume with the docker volume create command and supplied it my_volume as a name. We can also omit the volume name and just supply the container directory to --volume.

docker run --volume /var/lib/postgres/data

This volume is handled by docker itself which automatically creates the host volume under /var/lib/docker/volumes with a name generated from a random hash. This is essentially the equivalent to when we created a anonymous docker volume with the docker volume create command. This is an anonymous docker volume as there is no volume name provided. Note that using named volumes is a better idea. We can also provide the --volume flag the host path and its mapping to the container directly.

docker run --volume /var/lib/postgres/data:/var/lib/postgres/data

Here, we are mapping the /var/lib/postgres/data directory on our host machine to the /var/lib/postgres/data directory on the docker container. This type of volume allows us to specify where on the host the link between the host and the docker container is.

Docker Volumes Data Persistence Example

Lets now give an example of docker volumes at work by using the nginx docker image. To begin, lets create a volume called my_nginx_volume.

docker volume create my_nginx_volume

Now, lets create a container from the nginx image on docker hub using the docker run command. We will also supply the volume we made.

docker run --name my_nginx_c1 --volume my_nginx_volume:/usr/share/nginx/html -d nginx

Here we called our container my_nginx_c1 and mapped our volume to the /usr/share/nginx/html directory of the nginx container. This directory is the default location nginx shares content from. Now lets start a bash terminal session in the docker container with the docker exec command.

docker exec -it my_nginx_c1 bash

Now, navigate to the /usr/share/nginx/html directory.

cd /usr/share/nginx/html

Now lets make a change to the index.html file. If we print out the contents of index.html with the command cat index.html we will get the following.

Welcome to nginx!

Thank you for using nginx.

Now, change Welcome to nginx! to We've been here before! by using vim index.html. First install vim by running apt update and then apt install vim. After this, leave the bash session by running exit.

exit

Then stop and remove the docker container by running docker stop my_nginx_c1 followed by docker rm my_nginx_c1.

docker stop my_nginx_c1 && docker rm my_nginx_c1

Now, create another container called my_nginx_c2 by running the previous docker run command with a different container name. Note that we are using the same volume my_nginx_volume.

docker run --name my_nginx_c2 --volume my_nginx_volume:/usr/share/nginx/html -d nginx

Once again, create a bash session with the docker container by using the docker exec command.

docker exec -it my_nginx_c2 bash

Navigate to the /usr/share/nginx/html directory.

cd /usr/share/nginx/html

Once again, print out the contents of index.html with cat index.html.

cat index.html

We can see the the changes were persisted as We've been here before! is still present.

We've been here before!

Thank you for using nginx.

If we were not using docker volumes, then this data change would not have persisted when we created another container from this nginx image.