Persistent Data Storage in Docker: Docker Volumes and Bind Mounts

Share Now
4 min read
0
(0)
676

Accidently you executed docker rm -f mysql and that broke your entire application, but you are smart, you created the container again, but still the application is not able to bring old data.

You have seen some weird words in internet like –mount and then mydata:/some/path and you dont know what these means and how thats even related. Worry not, lets understand that and learn how to solve the problem of data lost and about the syntaxes that we see often on google or some document.

Lets see that together –

Docker containers are often ephemeral, meaning they’re designed to run processes and discard data upon exit(same as the first problem that we discussed above).

But what if you need certain data to persist beyond the lifecycle of a container? This is where persistent storage comes into play, allowing data to live on your host system(ex : laptop), even if containers are stopped, restarted, or deleted.

In this blog, we’ll cover three main aspects:

  1. What are Docker Volumes and Bind Mounts?
  2. How to Set Up Persistent Storage in Docker
  3. Benefits and Limitations of Different Docker Storage Options

Let’s dive into each phase to get a solid grasp on making data in Docker containers persist!

1. What Are Docker Volumes and Bind Mounts?

    Docker offers two primary ways to manage persistent data:

    • Volumes: Managed by Docker, volumes are stored in a specific Docker directory on the host, but Docker manages their lifecycle and storage location.
      • Remember, if we dont give that volume a name, docker creates a random number and that becomes difficult to manage or attach with other containers.
      • We human does not have any control, only docker can manage its lifecycle
      • To know its location, we can do inspect of the container and look for mounts block (docker inspect mysql-container)
    • Bind Mounts: Allows you to specify an exact path on your host machine to bind to a path within the container. With bind mounts, you control where the data lives.
      • Generally developers uses this and map their development workspace with some directory inside the container
      • The classic example is mapping the working space with nginx root path (source=$(pwd),target=/usr/share/nginx/)
      • Or, mapping the log directory of container

    Why Use Persistent Storage?

    Persistent storage is crucial when dealing with databases, configuration files, application logs, or any data you want to access or maintain across container restarts.

    For instance, without persistent storage, all the database data would disappear when a container is removed, making data recovery a challenge.

    2. Setting Up Persistent Storage in Docker

    Using Volumes in Docker

    We can create volumes in Docker in three ways: inline while creating a container, with docker volume create, or through docker-compose.

    Lets see all these 3 methods of creating volume in details below

    Method 1: Creating a Named Volume Inline with --mount

    To create a named volume directly when running a container, use the --mount option:

    docker run -d --name mysql-container --mount source=my_db_data,target=/var/lib/mysql mysql:latest

    Here:

    • source=my_db_data tells Docker to create a named volume called my_db_data.
    • target=/var/lib/mysql this specifies the path inside the container where the volume will be mounted.

    This approach is useful when you want Docker to manage the storage, ensuring data in /var/lib/mysql persists even if the container is removed.

    Method 2: Using docker volume create

    To have more control over volume creation, you can create a volume first and then mount it to a container:

    docker volume create my_app_data
    docker run -d --name app-container --mount source=my_app_data,target=/app/data myapp:latest

    Method 3: Using Docker Compose for Volumes

    Docker Compose simplifies multi-container setups by defining configurations in a YAML file. Here’s how you can set up a volume in docker-compose.yml:

    version: '3.8'
    services:
      db:
        image: mysql:latest
        volumes:
          - db_data:/var/lib/mysql
    
    volumes:
      db_data:

    In this example, db_data is a named volume that persists database files on the host.

    Lets see, how many of you got this as a question or curiosity, as how to know which path inside the container needs to be mapped with some named volume in local laptop/host machine.

    here, the colon (:) seperates the path between local & container and it can be read like this

    local_laptop_path:inside_container_path

    If you are curious, how to decide how to identify this path /var/lib/mysql inside the container db_data:/var/lib/mysql

    Then to find the answer of this, we have to go to the public repo and see the image and the key informations are already present there.

    Inspecting Docker Volumes

    To verify the volume and its mount details, use:

    docker inspect mysql-container

    In the output, look for the Mounts section to see details such as the Source (host path) and Destination (container path).

    "Mounts": [
                {
                    "Type": "volume",
                    "Name": "docker_dbdata",
                    "Source": "/var/lib/docker/volumes/docker_dbdata/_data",
                    "Destination": "/var/lib/mysql",
                    "Driver": "local",
                    "Mode": "z",
                    "RW": true,
                    "Propagation": ""
                }
            ],
    

    3. Using Bind Mounts for More Control

    Bind mounts offer a different approach by giving you full control over where the data lives on the host. You specify the exact path on your host machine that should be accessible from within the container.

    Creating a Container with a Bind Mount

    docker run -d --name web-container --mount type=bind,source=$(pwd)/my-website,target=/usr/share/nginx/html -p 80:80 nginx

    In this example:

    • type=bind indicates that we’re using a bind mount.
    • source=$(pwd)/my-website points to the my-website directory on the host machine.
    • target=/usr/share/nginx/html is the directory inside the container where my-website will be accessible.

    Just a side note:

    We can pass more than two bind mounts through command, but, here we will see its difficult and it may produce errors, so the discovery of docker compose made it better.

    docker run -d \
      --name website \
      -p 80:80 \
      --mount type=bind,source=$(pwd)/website_files,target=/usr/share/nginx/html \
      --mount type=bind,source=$(pwd)/nginx_logs/error.log,target=/var/log/nginx/error.log \
      website
    
    To know more about docker compose, please read it from here https://www.liainfraservices.com/blog/how-to-set-up-a-local-development-environment-using-docker-compose/

    If you inspect this container with docker inspect web-container, the Mounts section will reveal the host directory bound to the container’s filesystem:

    “Mounts”: [
    {
    “Type”: “bind”,
    “Source”: “/Users/macbook/my-website”,
    “Destination”: “/usr/share/nginx/html”,
    “RW”: true
    }
    ]

    Advantages of Bind Mounts

    • Full control: You decide exactly where on the host the data lives.
    • Real-time updates: Any changes made on the host directory are immediately reflected in the container, and vice versa.

    4. Benefits and Limitations of Docker Volumes vs. Bind Mounts

    Both storage methods have their own pros and cons:

    FeatureVolumesBind Mounts
    Managed byDockerHost (defined path)
    FlexibilityDocker decides storage locationUser specifies exact path
    SecurityMore secure, Docker manages permissionsLess secure, full access to host path
    Sharing DataEasily shared among containersPossible but with extra caution
    SuitabilitySuitable for app data, databases, logsGreat for development, real-time updates

    Example Scenarios:

    • Use named volumes for production databases, app data, or logs that need persistence but minimal intervention.
    • Use bind mounts in development to reflect host changes in real-time within containers, which is ideal for working with code or config files.

    Persistent data is a core aspect of any application relying on Docker containers, whether in development or production. Understanding when to use volumes versus bind mounts helps you make smart storage decisions that suit your application’s needs.

    By following this guide, you now know:

    1. How to create volumes and bind mounts in Docker.
    2. How to configure persistent data with Docker Compose.
    3. The benefits and limitations of each storage type.

    If you enjoyed so far, then I am sure you will enjoy this also where I dived deep into docker compose: https://www.liainfraservices.com/blog/how-to-set-up-a-local-development-environment-using-docker-compose/


    How useful was this post?

    Click on a star to rate it!

    Average rating 0 / 5. Vote count: 0

    No votes so far! Be the first to rate this post.

    Leave comment

    Your email address will not be published. Required fields are marked with *.