CD2: Running many containers together
Volumes: keeping data when containers go
🎯You'll be able to
Store a database's data on a volume so it survives the container being replaced, and choose between named volumes and bind mounts.
🏠The everyday picture
A shop can be repainted or the counter replaced, but the stock in the storeroom stays where it is. The storeroom isn't part of the counter.
📘What it really is
- A container's own files disappear when it's removed (CD1). For anything that must last, mount storage from outside:
- a named volume (
docker volume create routerani-dev-db), managed by Docker. Best for databases; - a bind mount (
-v /home/me/notes:/data), a folder from the host. Good for development and for config files, but tied to that host's folder layout and file permissions. - PostgreSQL keeps its data in
/var/lib/postgresql/datain the official image, so the volume is mounted there. -
A volume lives on until you delete it:
docker volume rm,docker compose down -v, orterraform destroyif Terraform created it. That's why-vdeserves a second look before you press Enter. -
A volume is not a backup. It lives on the same disk as the host; if the host or disk is lost, so is the volume. Back up with the database's own tools (
pg_dump, or a managed database's snapshots) to another place, and test restoring. -
Only one database server per data folder. Two PostgreSQL containers on the same volume at once can corrupt it. Replace a database container by stopping the old one before starting the new one.
📝A worked example
Input: in the finished kit, book seats with
curl -X POST localhost:8080/api/bookings -H 'content-type: application/json' -d '{"route_id":5,"seats":3}', then replace the database
container with terraform apply -replace=docker_container.db.
Expected output: the booking returns 201 with seats_left (37 on a fresh environment). After the replace, /api/routes still shows 37
seats left on route 5, because the data is on the volume routerani-dev-db. In the starter, which has no volume, the same steps bring
back 40 seats: the booking is lost. That's Project 1 test 9.
🌍Where it's used
- Databases, queues and search engines in containers all need volumes.
- Managed cloud databases (Amazon RDS, Cloud SQL) handle storage and backups for you; many teams use them instead (CD6).
- Kubernetes uses persistent volumes for the same purpose (CD5).
📝Case scenario
A small travel agency ran its booking database in a container with no volume. A routine Docker update restarted all containers from their
images, and three weeks of bookings vanished. They had nightly backups of the server's home folder, which didn't include Docker's internal
storage. Afterwards they used a named volume plus a nightly pg_dump copied to cloud storage, and restored it once a month to check.
🖱️Try it
Run docker volume ls, then docker volume inspect routerani-dev-db in the finished kit. Then run
docker exec routerani-dev-db pg_dump -U routerani routerani | head -20. Success: you've found where the data lives and made the start of a
backup you could copy elsewhere.
⚠️Common mistakes
- No volume on a database. Sign: data disappears after a redeploy. Fix: mount a named volume at the data folder.
- Treating the volume as the backup. Sign: no copy exists anywhere else. Fix: scheduled dumps to another place, and test restores.
- Running
down -vwithout thinking. Sign: a whole development database gone. Fix: usedownto stop; keep-vfor when you mean to delete.
🛠️For your project
Project 1 test 9 books seats, replaces the database container, and checks the booking is still there.
✅Quick check
Why isn't a volume a backup?
Show the answer
It's on the same host and disk; if they're lost, it's lost too.
Which folder needs the volume in the official PostgreSQL image?
Show the answer
/var/lib/postgresql/data.
