Docker Volumes and Bind Mounts: Managing Persistent Data
The Problem: Container Layers Are Ephemeral
Every write to a container's filesystem goes into a writeable layer that disappears when the container is removed. Databases, user uploads, and logs must be stored outside this layer.
Docker has two mechanisms: named volumes and bind mounts.
---
Named Volumes
# Create and use a named volume
docker volume create postgres_data
docker run -d -v postgres_data:/var/lib/postgresql/data postgres:16
# In Compose
services:
postgres:
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Named volumes are managed by Docker. They live at /var/lib/docker/volumes/ on Linux. They survive docker stop and docker rm. They are removed only by docker volume rm or docker compose down -v.
---
Bind Mounts
# Mount a host directory into the container
docker run -d -v /host/path:/container/path nginx
# Read-only bind mount
docker run -d -v /opt/configs:/etc/app:ro myapp
Bind mounts directly expose a host filesystem path. Changes in the container are immediately visible on the host and vice versa. Use for:
- Development (mount source code for live reload)
- Config files that you manage on the host
- Sharing data between host tools and containers
---
Inspecting Volumes
docker volume ls # list all volumes
docker volume inspect postgres_data # detailed info including mount point
docker inspect <container> | grep -A10 Mounts # what's mounted where
---
Backing Up a Named Volume
# Run a temp container, tar the volume contents to the host
docker run --rm -v postgres_data:/data:ro -v $(pwd)/backup:/backup alpine tar -czf /backup/postgres_data.tar.gz -C /data .
---
Restoring a Volume from Backup
docker volume create postgres_data_restored
docker run --rm -v postgres_data_restored:/data -v $(pwd)/backup:/backup:ro alpine tar -xzf /backup/postgres_data.tar.gz -C /data
---
tmpfs Mounts (RAM-backed)
For temporary data that must not persist to disk:
docker run --tmpfs /tmp:rw,noexec,nosuid,size=64m myapp
Useful for session data, temp files, or any data that should vanish on restart and should be fast.
---
Common Mistakes
Problem: data not persisting after docker compose down -v Cause: -v removes named volumes. Use docker compose down (no -v) to preserve data.
Problem: permission errors writing to a bind mount Cause: the process inside the container runs as a user whose UID does not match the file owner on the host. Fix: either match UIDs or use chown on the host path.
# Check the UID the process uses inside the container
docker exec <container> id
# Fix ownership on the host
chown -R 1000:1000 /host/path
Problem: writes to a volume are slow on Mac/Windows Cause: Docker Desktop uses a VM; bind mounts cross the VM boundary. Use named volumes for database data on non-Linux hosts.
Practice in the ShellGenius Docker Labs — the volume-persistence challenge puts you in a scenario where data loss is happening and you must fix it.