Persisting Data In Docker: Volumes & Bind Mount

Persisting Data In Docker: Volumes & Bind Mount

Containers have changed how developers work, making developing and deploying code easier. In today's dynamic world of software development, it’s important to understand how to work with Docker. So I always tried covering one topic in the blog to help you understand Docker easily. In this article, we’ll explain the basics of Docker volumes in a straightforward way.

Docker Volume

Docker Volume is a mechanism that helps us to store data outside the container. They prevent data loss when your container stops. You can easily connect the volume to a new container, and your data from the previous one will carry over to the new container.

When a container usually writes something it writes in its writable layer and on stopping that container all data is deleted from the container. So in order to solve this issue what we do is we mount a special folder in the container file system. So if the container wants to add something on that particular file system point where volume is mounted in that case data is not written on the writable layer instead it is written in volume.

All volumes are managed by Docker and stored in a dedicated directory on your host, usually /var/lib/docker/volumes for Linux systems. Named volumes persist while anonymous volumes are deleted as the container to which it is mounted is stopped or removed, more about it ahead.

Docker Mount

Bind Mount has been made available since the early stage of Docker. Bind mounts will mount a file or folder from your host machine to the container file system. When we start a container that file or folder does not necessarily exist in the container. If it doesn’t exist, it will be created on demand. Now when we change something on that folder (that is mounted) it will be reflected inside the container and vice versa.

Now it might introduce some security risks that you need to handle because if we change something from the container it will be reflected in the host file system as well.

We usually use mounts when we are developing. During development, we mount our code folder into the container. Then, when we make changes to the code, it will reflect in the container in real time without us needing to create a new image.

When To Use What?

Docker volumes and mounts are both ways to manage data in containers, but they serve different purposes.

Volumes are handy to use, they are safe vaults for your container. It is managed by docker itself and stored separately on your computer. You can attach and detach as you need just like the portable hard disk. It is used where we need to store data and persist it even after the container is removed, like when we want to use a database and want to store data across containers.

On the other hand, mounts are like open windows between the docker filesystem and the host machine. They’re useful during development when you want changes in your code to show up in the container. They come in handy during development they allow us as a user to mount the code folder to the container so when we change something in the code folder it almost instantly shows up in the container.

It’s a two-way street, meaning that changes made within the container’s folder can also affect the host folder. While this two-way connection enhances flexibility, it can introduce security risks. However, these risks can be addressed through proper security precautions.

Example: Using Docker Volumes

Let’s see volumes in action and how can we define them while spinning up containers.

docker run -it -v test_volume:/test --name ubuntu_container ubuntu:22.04

The above command will spin up the container and name it ubuntu_container, by adding the -v flag we are defining a volume. Now there are 2 types of volumes here we are defining named volumes but we do have an unnamed volume known as an anonymous volume.

When the container starts we will get terminal access to it where we can interact with the terminal due -it what we add.

ls /test

Now if we list the test folder it will be empty which means it was created on the fly when we started the container which is an indication that volumes were successfully mounted.

Now let's make a file inside the test with some text in it.

$ echo "testing volumes in docker" > /test/volumes

$ cat /test/volumes
testing volumes in docker

Now if we exit the container using the exit command or Ctrl+C it will exit the container and it will be stopped as there are no other processes running on the container.

docker run -it -v test_volume:/test --name ubuntu_container2 ubuntu:22.04

Now we spin up another container and attach the same volume to it, remember named volumes persist across the container.

cat /test/volumes

Now if we look into the same file we created it will be there because volume persisted and it reflects the changes made by another container at some point in time.

Creating Volumes Manually

We saw previously how we can use named volumes to persist data. The volumes there were created by docker if not exist but remember we can also create volumes on our

docker volume create test_name_volume

You can list all created volumes by running the ls command given to us by the docker CLI

docker volume create app_data

You can use this volume to create containers by attaching them with container on run time like above

docker run -it -v test_name_volume:/test --name ubuntu_container3 ubuntu:22.04

Read Only Volumes

We can make a volume read-only so that the container can read from that volume and can not write. It can be used if you have any security concerns depending upon the requirement of the application.

docker run -it -v test_name_volume:/test:ro ubuntu:22.04

Defining Volumes In Dockerfile

We can define volumes in Dockerfile so that we don't have to define it every time using the -v flag.

FROM ubuntu:22.04
VOLUME /test_name_volume

The above VOLUME Command will create an anonymous volume and will attach it to a container that will be created by this image.

Defining Volumes In Compose File

services:
  app:
    image: ubuntu:22.04
    volumes:
      - test_name_volume:/data
volumes:
  test_name_volume:

By defining the volumes section in compose we are telling docker to create volume and then we are mounting it with our so-called service.

If we want to tell compose that volume is already created and just pick that volume and mount add this option into volume section.

volumes:
  test_name_volume:
    external: true

we can also define drivers and a lot more here which is not the part of blog scope.

Inspecting A Volume

You can inspect a volume by using the inspect command:

docker volume ls
DRIVER      VOLUME NAME
local       test_name_volume
local       test_volume
docker volume inspect test_name_volume
[
    {
        "CreatedAt": "2023-10-27T14:05:55Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/test_name_volume/_data",
        "Name": "test_name_volume",
        "Options": null,
        "Scope": "local"
    }
]

Removing A Volume

$ docker volume rm test_name_volume
test_name_volume

We can delete a volume using the above command.

Defining Bind Mount

Now let’s quickly look into how we can define Bind Mount while running a container.

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

While mounting a bind mount we have to give a path to both folders we need to connect. Remember that we need to define the absolute path in order for that to work for the host folder.

A Quick Update

The methods discussed above to define volumes are still in use but docker has also introduced a new way of defining these.

docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest

The above example is taken from their documentation and now we can use the — mount flag to define bind mount or volumes. There is also one more type which is — mount type=volume that will be used to define volumesdoc . You can check more details on their documentation Docker Bind Mount Using — mount Flag.

Conclusion

Hope you found this blog helpful. I have tried to cover all the basics about volume or mount you need to know as beginners. There are many more things about this topic that I will cover in future blogs.

If you found this content helpful, please show your support by giving it a clap, following me on LinkedIn and YouTube, and considering making a small contribution to Buy Me a Coffee☕️. Your support is greatly appreciated!

Did you find this article valuable?

Support Muhammad Younus by becoming a sponsor. Any amount is appreciated!