Volumes and Persistent Data
Chapter 4 — Volumes and Persistent Data
Back in Chapter 1 we noted that containers are ephemeral — anything written inside a container is lost the moment the container is removed. For a web server serving static files that's fine. For a database storing your data, or a development environment where you want your edits to survive, it's a problem. Volumes are Docker's answer.
This chapter covers how data loss actually happens, the three types of storage Docker provides, and the two you'll use every day: named volumes and bind mounts.
1. The Data Loss Problem
Every container has a thin writable layer on top of its read-only image layers.
Any file created or modified inside the container goes into this writable layer.
When you remove the container with docker rm, that writable layer
is deleted with it — permanently.
💥 docker rm
This happens even if you only run docker rm — not docker stop.
Stopping a container leaves its writable layer intact; removing it deletes the layer.
The solution is to store data outside the container's writable layer,
somewhere that persists independently of any individual container.
2. Three Types of Docker Storage
For the rest of this chapter we'll focus on named volumes and bind mounts — the two you'll use in almost every real scenario.
3. Named Volumes
A named volume is a storage area that Docker creates and manages. You give it a name, mount it into one or more containers at a specific path, and Docker handles where the data actually lives on disk. You don't need to know or care about the exact host path — Docker manages it for you.
mysql-data volume — not inside the container itself.
Managing Named Volumes
| Command | What it does |
|---|---|
| docker volume create NAME | Create a named volume manually |
| docker volume ls | List all volumes |
| docker volume inspect NAME | Show volume details including where it lives on disk |
| docker volume rm NAME | Delete a volume (must not be in use by any container) |
| docker volume prune | Remove all volumes not used by any container — careful! |
docker container prune which only removes stopped containers,
docker volume prune deletes the actual data. Always double-check
which volumes are safe to remove before running it.
4. Bind Mounts
A bind mount maps a specific folder on your host machine directly into the container. Unlike named volumes, you control exactly where the data lives — it's just a regular folder on your computer. This makes bind mounts ideal for development: edit files in your editor on the host, and the container sees the changes instantly.
index.html
style.css
about.html
← edit files here in VS Code
index.html
style.css
about.html
← nginx serves from here
The :ro at the end means read-only — the container can read
the files but cannot modify them. This is appropriate for serving a website.
For a development environment where the container also writes files (logs,
compiled output), leave off :ro.
index.html in your editor on the host, save a change, and
refresh your browser — you'll see the change immediately without restarting
the container. The container is always reading the actual files on your disk.
5. Named Volume vs Bind Mount — Which to Use
| Situation | Use | Why |
|---|---|---|
| Database data (MySQL, PostgreSQL, Redis) | Named volume | You don't need to browse the data files directly; Docker manages them safely |
| Serving website files you're editing | Bind mount | You edit files on the host in your editor and see changes live |
| Source code for a dev environment | Bind mount | Your editor lives on the host; the container runs/builds the code |
| Config files (nginx.conf, php.ini) | Bind mount | Easy to edit on host, version-control alongside your project |
| Shared data between multiple containers | Named volume | Mount the same volume into multiple containers — they share the data |
| Production app data | Named volume | More portable — not tied to a specific host path |
6. Practical Example — nginx with Custom Config and Site Files
This is a preview of Chapter 7's Apache scenario, but with nginx to show the pattern now. We'll mount both the site files and a custom config file from the host:
7. Backing Up and Restoring Volumes
Named volumes are managed by Docker, so they're not immediately accessible as a folder. The standard backup technique is to spin up a temporary container, mount the volume, and archive its contents:
mysqldump
(a logical backup) rather than copying the raw data files. Raw file copying
can produce a corrupt backup if MySQL is writing at the same time. Use:
docker exec mydb mysqldump -u root -psecret myapp > backup.sql
8. Common Volume Patterns
- Prove containers are ephemeral. Run
docker run -it --name test ubuntu bash, create a file inside withecho "hello" > /myfile.txt, then exit and rundocker rm test. Start a new ubuntu container and confirm/myfile.txtdoesn't exist. This is the problem volumes solve. - Persist data with a named volume. Create a named volume called
test-voland rundocker run -it --rm -v test-vol:/data ubuntu bash. Inside, writeecho "persisted!" > /data/hello.txtand exit. Run a second container with the same volume mount and confirm the file is still there withcat /data/hello.txt. - Serve your website with a bind mount. Create a folder called
mysiteon your host with a simpleindex.html. Rundocker run -d -p 8080:80 -v /full/path/to/mysite:/usr/share/nginx/html:ro nginx:alpine. Visithttp://localhost:8080to confirm it serves your file. Now editindex.htmlon your host and refresh — you should see the change immediately without restarting the container. - Inspect a volume. Run
docker volume lsto see your volumes, thendocker volume inspect test-volto find its Mountpoint on disk. On Linux you can navigate directly to that path and see your files. On Windows with Docker Desktop, note the WSL2 path shown. - Back up a named volume. Using the backup command from Section 7, create a
.tar.gzbackup of yourtest-volinto abackups/folder on your host. Then create a new volume calledtest-vol-restore, restore the backup into it, and verify the file is there by running a container with the restored volume mounted.