Docker Volumes
Persist container data with Docker volumes, bind mounts, and tmpfs mounts, and learn when to use each, with backup and Compose examples.
By default, everything a container writes goes into its writable layer, which is deleted when the container is removed. Volumes and mounts let data live outside the container so it survives restarts, upgrades, and replacement. Getting storage right is essential for databases, uploads, and any stateful workload.
The Three Mount Types
| Aspect | Volume | Bind mount | tmpfs mount |
|---|---|---|---|
| Storage location | Managed by Docker (/var/lib/docker/volumes/... on Linux) |
Any host path you specify | Host memory only |
| Created by | docker volume create or automatically |
You, on the host | Docker at container start |
| Survives container removal | Yes | Yes (it is your host directory) | No |
| Portability | High, independent of host layout | Depends on host path existing | Not applicable |
| Typical use | Databases, persistent app data | Source code in development, config files | Secrets or scratch data that must not touch disk |
| Pre-populated from image | Yes, for new empty volumes | No, host content hides the image content | No |
| Works on Linux only | No | No | Yes (Linux containers) |
Named Volumes
# Create a volume and use it for PostgreSQL data
docker volume create pgdata
docker run -d --name db \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# Remove the container; the data remains
docker rm -f db
# Start a new container with the same data
docker run -d --name db2 \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
docker volume ls
# DRIVER VOLUME NAME
# local pgdata
docker volume inspect pgdata
# "Mountpoint": "/var/lib/docker/volumes/pgdata/_data"
If you use -v name:/path and the volume does not exist, Docker creates it automatically. Volumes can be shared by several containers.
Bind Mounts
A bind mount maps an existing host file or directory into the container. It is useful in development so code changes appear instantly.
docker run -d --name web -p 8080:80 \
-v "$(pwd)/site:/usr/share/nginx/html:ro" \
nginx:1.27
:ro makes the mount read-only inside the container. The --mount syntax is more explicit and recommended for clarity:
docker run -d --name web -p 8080:80 \
--mount type=bind,source="$(pwd)/site",target=/usr/share/nginx/html,readonly \
nginx:1.27
docker run -d --name db \
--mount type=volume,source=pgdata,target=/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=secret postgres:16
With -v, a missing host path is created as a directory automatically; with --mount type=bind Docker returns an error instead, which catches typos.
tmpfs Mounts
docker run -d --name cache \
--tmpfs /tmp:rw,size=64m \
nginx:1.27
Data in a tmpfs mount lives in memory and disappears when the container stops.
Volumes in Docker Compose
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
web:
image: nginx:1.27
volumes:
- ./site:/usr/share/nginx/html:ro
volumes:
pgdata:
Named volumes are declared in the top-level volumes: key. docker compose down keeps them; docker compose down -v deletes them.
Backing Up and Restoring a Volume
Use a temporary container that mounts the volume and a host directory:
# Backup
docker run --rm \
-v pgdata:/data:ro \
-v "$(pwd)":/backup \
alpine tar czf /backup/pgdata.tar.gz -C /data .
# Restore into a new volume
docker volume create pgdata_restored
docker run --rm \
-v pgdata_restored:/data \
-v "$(pwd)":/backup \
alpine tar xzf /backup/pgdata.tar.gz -C /data
For databases, a logical backup such as pg_dump is safer than copying files from a running instance.
Anonymous Volumes and the VOLUME Instruction
A VOLUME /data instruction in a Dockerfile (or -v /data at run time) creates an anonymous volume with a random name if you do not mount anything there. These are easy to lose track of and pile up. Prefer explicit named volumes.
docker volume ls -f dangling=true # volumes not used by any container
docker volume prune # remove unused local volumes
Common Mistakes
- Keeping database data in the container layer. Removing the container deletes it. Mount a volume.
- Bind-mounting over image content unintentionally. A bind mount hides whatever the image had at that path, such as installed dependencies in
node_modules. - Permission problems with bind mounts. The container user's UID and GID must be able to read and write the host path.
- Running
docker volume pruneordocker compose down -vwithout checking. Both permanently delete data. - Relying on anonymous volumes. They are hard to identify and are often left behind.
Best Practices
- Use named volumes for persistent application data and bind mounts for development source code.
- Prefer the
--mountsyntax in scripts for explicit, strict behaviour. - Mount configuration and secrets as read-only (
:ro) wherever possible. - Back up volumes regularly and test restores.
- Keep containers stateless so they can be replaced freely.
Interview Questions
1. What is the difference between a volume and a bind mount?
A volume is created and managed by Docker in its own storage area and is independent of the host's directory layout. A bind mount maps a specific host path into the container. Volumes are preferred for production data and are portable; bind mounts suit development and sharing host config files.
2. How do you persist data for a database container?
Mount a named volume at the database's data directory, for example -v pgdata:/var/lib/postgresql/data for PostgreSQL. The data then outlives the container and can be attached to a new container.
3. What happens to a volume when the container is removed?
It stays. docker rm does not delete named volumes. Anonymous volumes are only removed with docker rm -v or when started with --rm. Explicit removal needs docker volume rm or docker volume prune.
4. What is a tmpfs mount and when would you use it?
A tmpfs mount stores data in host memory and never writes it to disk. It is useful for temporary or sensitive data that must not persist, and it disappears when the container stops.
5. How can multiple containers share data?
Mount the same named volume into each container. For concurrent writers you must ensure the application handles locking itself, since Docker does not coordinate access.
6. How would you back up a Docker volume?
Start a short-lived container that mounts the volume read-only plus a host directory, then archive the contents with tar. For databases prefer native tools such as pg_dump for consistency.
Summary
- Container writable layers are temporary; use volumes for persistent data.
- Named volumes are Docker-managed and portable; bind mounts map host paths; tmpfs is memory-only.
--mountis explicit and stricter than-v.docker compose down -vand volume pruning delete data permanently.
Continue Learning
Previous: Docker Commands | Next: Docker Networking
Was this guide helpful?
CodeWithVenu is free to read, with no paywall. If this guide saved you time or helped you prepare, a small voluntary contribution helps me write more practical tutorials, architecture guides, and interview-prep content.