On this page
The core idea
Each container gets a thin writable layer on top of its image. Anything the application writes there, such as uploaded files or a database's data directory, lives only as long as that container. Removing the container to deploy a new version deletes the data with it. Volumes are storage managed outside the container's lifecycle and mounted into it at a path. Bind mounts map a host directory into the container and are convenient in development. Treating containers as disposable and data as separately managed is the core habit.
A practical approach
Step 1
List every path your application writes to at runtime: databases, uploads, caches and logs.
Step 2
For data that must survive, mount a named volume at that path, for example a volume for a database's data directory.
Step 3
Use bind mounts in development for source code you want to edit live, but avoid them for production data.
Step 4
Prefer managed services for production databases and file storage when available; they handle backups and replication.
Step 5
Back up volumes on a schedule and practise restoring them, because a volume protects against container removal, not against disk failure or accidental deletion.
Worked example
A team runs PostgreSQL in Docker Compose for a demo environment without a volume. After running docker compose down and up to apply a configuration change, every test account and course disappears. Adding a named volume mounted at /var/lib/postgresql/data keeps the data across restarts, and a nightly dump to object storage covers the case where the volume itself is lost.
A mistake to avoid
Do not assume docker compose down is harmless. With the -v flag it also removes named volumes declared in the file. Check the command before running it against an environment that holds data you care about.
Try it yourself
Start a database container without a volume, add some rows, remove and recreate the container and confirm the data is gone. Repeat with a named volume and confirm it survives, then practise backing it up and restoring into a fresh container.
Your implementation checklist
- I know every path my container writes to
- Persistent data lives in volumes or external services
- Bind mounts are used for development convenience only
- Volumes are backed up and restores are tested
- I check destructive Compose commands before running them
Share or cite this guide
Innovate with Ajay Editorial (2026-10-07). Keep Container Data Safe with Volumes, Not the Container Layer. https://innovatewithajay.com/blogs/keep-container-data-safe-with-volumes
