6 Using Docker volumes for persistent storage
Containers excel at running stateless workloads because every instance starts from the same image and can be replaced with zero-downtime rolling updates. However, many applications include stateful components that read and write data. Inside a container, the filesystem is composed of read-only image layers plus a per‑container writable layer using copy‑on‑write. Edits made at runtime live only in that writable layer and vanish when the container is removed, so any state stored there is transient. To persist data beyond a container’s lifecycle, Docker provides volumes and filesystem mounts that sit outside the container’s ephemeral writable layer.
Docker volumes are storage units managed by Docker and attached to containers as directories. They persist independently of containers, making them ideal for application data that must survive upgrades. Volumes can be created explicitly and attached with run-time flags, or declared in images with the VOLUME instruction so containers default to writing to persistent storage. Although volumes can be shared between containers (for example via the volumes-from flag), many stateful apps expect exclusive access to files, so sharing can introduce correctness issues. Best practice is to use named volumes and reattach them across application versions to preserve data; image authors can include VOLUME as a fail-safe, while operators should explicitly specify named volumes to control where data lives.
Bind mounts map host paths directly into containers, enabling scenarios like using host-backed SSDs/RAID, live-editing source code during development, or injecting configuration via read-only mounts. They are transparent to the app but require careful handling: a mounted directory replaces the target path’s contents (it doesn’t merge with files from the image), single-file mounts merge on Linux but aren’t supported on Windows, and path conventions differ between OSes. Using distributed storage (NFS/SMB/cloud shares) may also limit filesystem features and impact performance. In practice: use the writable layer only for ephemeral caches; prefer Docker volumes for persistent application state; use local bind mounts for development and config overlays; treat distributed bind mounts with caution; and rely on image layers for read-only application content.
Running containers that write data, and checking the data
The container filesystem is built from image layers and a writeable layer.
Modifying a container’s state and running it again
Modifying files in a container does not affect the image, and the container’s data is transient.
Running a container with a volume declared in the Dockerfile
The never-ending to-do list, running in a container using a Docker volume
Running containers with dedicated and shared volumes
Creating a named volume and using it to persist data between container updates
The all-new to-do app UI
Sharing a directory on the host with a container using a bind mount
Using bind mounts to load read-only configuration files into containers
Bind mount directories shadow the target directory if it exists.
Bind mounts with a single file as the source work on Linux but not on Windows.
Distributed storage systems may not provide all the usual filesystem features.
The container filesystem is created from the union of multiple sources.
Lab
We’ll put those pieces together in this lab. It’s back to the good old to-do list app, but this time with a twist. The app will run in a container and start with a set of tasks already created. Your job is to run the app using the same image but with different storage options, so that the to-do list starts off empty, and when you save items they get stored to a Docker volume. The exercises from this chapter should get you there, but here are some hints:
- Remember it’s docker rm -f $(docker ps -aq) to remove all your existing containers.
- Start by running the app from diamol/ch06-lab:2e to check out the tasks.
- Then you’ll need to run a container from the same image with some mounts.
- The app uses a configuration file—there’s more in there than settings for the log level.
My sample solution is on the book’s GitHub repository if you need it, but you should try to work through this one because container storage can trip you up if you haven’t had much experience. There are a few ways to solve this. My solution is here: https://github.com/sixeyed/diamol/blob/2e/ch06/lab/README.md.
Learn Docker in a Month of Lunches, Second Edition ebook for free