Docker Volumes¶
Persistent data storage for Docker containers
Overview¶
Docker volumes provide persistent storage that survives container lifecycle. They are the preferred mechanism for persisting data generated by Docker containers.
flowchart LR
subgraph Host
A[Docker Volume]
B[Bind Mount]
end
subgraph Container
C[/app/data]
D[/app/config]
end
A -->|volume| C
B -->|bind| D
Volume Types Comparison¶
| Type | Location | Management | Use Case |
|---|---|---|---|
| Named Volume | /var/lib/docker/volumes/ |
Docker CLI | Production data |
| Anonymous Volume | /var/lib/docker/volumes/ |
Automatic | Temporary data |
| Bind Mount | Anywhere on host | Manual | Development, configs |
| tmpfs | Memory only | Automatic | Sensitive data |
Named Volumes¶
Create Volume¶
# Create a named volume
docker volume create my-data
# List all volumes
docker volume ls
# Inspect volume details
docker volume inspect my-data
Use Volume in Container¶
# Mount volume to container
docker run -v my-data:/app/data \
--name my-container \
nginx:latest
# Using --mount (more explicit)
docker run --mount source=my-data,target=/app/data \
--name my-container \
nginx:latest
Docker Compose¶
version: '3.8'
services:
db:
image: postgres:15
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
driver: local
Bind Mounts¶
Mount host directory directly into container:
# Basic bind mount
docker run -v /host/path:/container/path \
--name my-container \
nginx:latest
# Read-only bind mount
docker run -v /host/path:/container/path:ro \
--name my-container \
nginx:latest
Development Example¶
# Mount source code for development
docker run -v $(pwd)/src:/app/src \
-v $(pwd)/config:/app/config:ro \
--name dev-container \
node:18
Volume Management¶
List Volumes¶
# List all volumes
docker volume ls
# Filter by name
docker volume ls --filter name=my-
# Show only dangling volumes
docker volume ls --filter dangling=true
Remove Volumes¶
# Remove specific volume
docker volume rm my-data
# Remove container and its volume
docker rm -v my-container
# Remove all unused volumes
docker volume prune
# Remove all unused volumes (force)
docker volume prune -f
Backup Volume¶
# Backup volume to tar file
docker run --rm \
-v my-data:/source:ro \
-v $(pwd):/backup \
alpine tar cvf /backup/my-data-backup.tar /source
# Restore from backup
docker run --rm \
-v my-data:/target \
-v $(pwd):/backup \
alpine tar xvf /backup/my-data-backup.tar -C /target --strip 1
Volume vs Bind Mount¶
When to Use Volumes¶
✅ Production environments ✅ Data that needs to persist ✅ Sharing data between containers ✅ Backup and migration requirements ✅ Cross-platform compatibility
When to Use Bind Mounts¶
✅ Development (live code reload) ✅ Configuration files ✅ Specific host file access needed ✅ Build contexts
Volume Drivers¶
Local Driver Options¶
# Create volume with specific options
docker volume create \
--driver local \
--opt type=nfs \
--opt o=addr=192.168.1.100,rw \
--opt device=:/path/to/share \
nfs-volume
External Storage¶
Best Practices¶
- Use named volumes for important data
- Set appropriate permissions on bind mounts
- Backup volumes regularly for critical data
- Clean up unused volumes with
docker volume prune - Use read-only mounts when possible (
:ro)
Troubleshooting¶
Permission Issues¶
# Check volume permissions
docker run --rm -v my-data:/data alpine ls -la /data
# Fix permissions
docker run --rm -v my-data:/data alpine chown -R 1000:1000 /data
Volume Not Found¶
# Ensure volume exists
docker volume ls | grep my-data
# Create if missing
docker volume create my-data