Docker Volumes
Docker Volumes
Section titled “Docker Volumes”Containers are ephemeral — when a container is removed, all data inside it is lost. Volumes and bind mounts persist data beyond the container lifecycle.
Three Storage Options
Section titled “Three Storage Options”| Type | Description | Use Case |
|---|---|---|
| Volume | Managed by Docker, stored in Docker’s directory | Database data, persistent state |
| Bind mount | Maps a host directory into the container | Source code, config files |
| tmpfs | Stored in memory only | Sensitive data, temp files |
Named Volumes
Section titled “Named Volumes”# Create a volumedocker volume create my-data
# Use in a containerdocker run -v my-data:/app/data my-image
# List volumesdocker volume ls
# Inspect a volumedocker volume inspect my-data
# Remove a volumedocker volume rm my-data
# Remove all unused volumesdocker volume pruneIn Docker Compose:
services: db: image: postgres:16 volumes: - postgres-data:/var/lib/postgresql/data
volumes: postgres-data: # Docker manages thisVolumes persist when you run docker compose down. They’re removed with docker compose down -v.
Bind Mounts
Section titled “Bind Mounts”Maps a host directory or file into the container:
# Mount source code (absolute path required)docker run -v /Users/me/myapp:/app my-image
# Read-only bind mountdocker run -v /Users/me/config:/app/config:ro my-imageIn Docker Compose:
services: api: volumes: - .:/app # current directory → /app in container - ./config:/app/config:roBind Mounts for Development
Section titled “Bind Mounts for Development”The most common use: mount source code so changes reflect immediately without rebuilding:
services: api: build: . volumes: - .:/app # mount source - /app/node_modules # anonymous volume prevents host from overwriting node_modules command: npm run devThe anonymous volume /app/node_modules ensures the container’s node_modules (installed during build) isn’t overwritten by the empty node_modules on the host.
Volume Backup and Restore
Section titled “Volume Backup and Restore”# Backup a volume to a tar filedocker run --rm \ -v my-data:/source \ -v $(pwd):/backup \ alpine tar czf /backup/my-data-backup.tar.gz -C /source .
# Restore from backupdocker run --rm \ -v my-data:/target \ -v $(pwd):/backup \ alpine tar xzf /backup/my-data-backup.tar.gz -C /targetSharing Data Between Containers
Section titled “Sharing Data Between Containers”Named volumes can be mounted in multiple containers simultaneously:
services: api: volumes: - shared-uploads:/app/uploads
worker: volumes: - shared-uploads:/app/uploads
volumes: shared-uploads:Volume Drivers
Section titled “Volume Drivers”For production, volumes can use external storage:
volumes: my-data: driver: local # default driver_opts: type: nfs o: addr=192.168.1.100,rw device: ":/nfs/data"Cloud volume drivers: rexray/ebs (AWS), azurefile (Azure), gcepersistentdisk (GCP).
Read-Only Containers
Section titled “Read-Only Containers”Make the root filesystem read-only and use volumes for writable paths:
docker run \ --read-only \ -v /tmp \ # writable tmpfs -v my-logs:/app/logs \ # writable volume my-imageWhen to Use What
Section titled “When to Use What”- Named volumes — database data, anything that needs to persist across container recreations
- Bind mounts — development (live source code changes), configuration files, secrets files
- tmpfs — temporary files, secrets that shouldn’t touch disk
Never store database data in the container’s writable layer — always use a named volume.