Docker Volumes & Data Persistence
Containers are ephemeral — their writable layer dies with them. Volumes, bind mounts and tmpfs mounts are the three ways to persist or share data safely.
What is this?
Docker offers three storage options: named volumes (managed by Docker in its storage area), bind mounts (any host directory mapped into the container), and tmpfs (in-memory only). Named volumes are the recommended default for persistent data.
Why do you need it?
- Databases and application state must survive container recreation.
- Volumes are portable with the container and shareable between containers.
- tmpfs gives you fast in-memory storage that never touches disk.
- Persisting data to the host makes debugging easy: inspect files directly.
Mental model
A USB drive you plug into a computer
A Docker volume
The drive keeps your files even when the computer reboots, and you can move it between computers — exactly how a volume outlives containers and can be shared.
How it works
- Named volumes live under /var/lib/docker/volumes on the host, managed by Docker.
- A volume is mounted at a container path; writes go to the volume, not the container's writable layer.
- Bind mounts map any host path directly (./data:/app/data) and reflect changes instantly.
- tmpfs mounts exist only in memory and are destroyed when the container stops.
- Backing up a named volume means exporting its mount point contents (or using docker run --volumes-from with a tar).
Three storage types and where data lives.
Key commands
docker volume create mydataCreate a named volume explicitly.
docker run -v mydata:/app/data appMount a named volume at /app/data.
docker run -v $(pwd)/config:/etc/app/config appBind-mount a host directory (absolute path required).
docker volume lsList volumes.
docker run --tmpfs /cache appMount an in-memory tmpfs at /cache.
Examples
Persist a database with a named volume
docker volume create pgdatadocker run -d --name postgres \ -e POSTGRES_PASSWORD=secret \ -v pgdata:/var/lib/postgresql/data \ postgres:16 # Stop, remove, and recreate the container — data survives:docker rm -f postgresdocker run -d --name postgres \ -e POSTGRES_PASSWORD=secret \ -v pgdata:/var/lib/postgresql/data \ postgres:16The named volume pgdata stores PostgreSQL's data directory. Even after the container is deleted, the volume remains and the new container mounts the same data.
In production
- Database engines persist via named volumes (Postgres, MySQL, Redis).
- Bind mounts are used in development for hot reload; rarely in production.
- Shared config/secrets via read-only bind mounts from the host.
- tmpfs for ephemeral caches or tmpdirs that should never persist.
Best practices
- Prefer named volumes over bind mounts — Docker manages pathing and permissions.
- Mount config as read-only (:ro) to prevent accidental modification.
- Back up volumes regularly (dump the DB, not the volume directory blindly).
- Don't mount the Docker socket into containers unless absolutely necessary.
Common mistakes
- Storing data in the container's writable layer — it's lost on docker rm.
- Using relative paths in bind mounts (must be absolute or $PWD).
- Assuming volumes are deleted with docker rm — they are not; use docker volume rm.
- Mounting volumes with permission mismatches (UID/GID issues).
Common issues
Permission denied when writing to a volumeContainer process UID doesn't match host directory ownership.
Run the container with a matching UID (docker run --user $(id -u):$(id -g)), or chown the host dir.
Data missing after container recreationVolume wasn't mounted, or data went to the writable layer.
Verify with docker inspect that the mount path matches the app's data dir.
docker volume rm: volume is in useA container (even stopped) references it.
Remove referencing containers first, then the volume.
Debugging tips
- docker volume ls and docker volume inspect to find and inspect volumes.
- docker inspect -f '{{ json .Mounts }}' ID to see exactly what's mounted.
- docker run --rm -v mydata:/data alpine ls -la /data to inspect volume contents.
- For bind mounts, check SELinux/AppArmor on Linux hosts.
Interview checkpoint
Hands-on lab
- Create and use named volumes
- Persist a database across container recreation
- Back up and restore volume data
- Use bind mounts for development
Persistent Database with Volumes
30 min · intermediate
Quick quiz
What happens to data in a container's writable layer after docker rm?
Which option mounts an in-memory filesystem?
Named volumes are removed automatically when you run docker rm.
Cheat sheet
docker volume create VCreate named volume-v V:/pathMount named volume-v /host:/pathBind mount (absolute path)--tmpfs /pathIn-memory mountdocker volume lsList volumesdocker volume rm VDelete volume