Introduction to Volumes
Docker volumes provide persistent storage for containers. By default, container data is ephemeral - when a container is removed, its data disappears. Volumes solve this problem.
Why Volumes?
Container filesystems are:
- Ephemeral: Data is lost when container is removed
- Tied to container lifecycle: Can't easily share data
- Write-heavy: Using container's writable layer impacts performance
Volumes provide:
- Persistence: Data survives container removal
- Sharing: Multiple containers can access the same data
- Performance: Better I/O performance than container filesystem
- Backup: Easy to back up and migrate
Storage Options
Docker provides three ways to persist data:
┌────────────────────────────────────────────────────────────────┐
│ Container │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Container Filesystem (tmpfs) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Volume │ │ Bind │ │ tmpfs │ │
│ │ │ │ Mount │ │ Mount │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
Docker-managed Host filesystem Host memory
/var/lib/docker/ Anywhere on host (RAM only)
volumes/
| Type | Location | Use Case |
|---|---|---|
| Volume | Docker-managed area | Production data, databases |
| Bind Mount | Host filesystem path | Development, config files |
| tmpfs | Host memory (RAM) | Sensitive data, caches |
Creating Volumes
# Create a named volume
docker volume create my-volume
# List volumes
docker volume ls
# Inspect a volume
docker volume inspect my-volume
# Output:
[
{
"CreatedAt": "2024-01-15T10:30:00Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
"Name": "my-volume",
"Options": {},
"Scope": "local"
}
]
Using Volumes with Containers
Using -v (short syntax)
# Named volume
docker run -v my-volume:/app/data nginx
# Anonymous volume (auto-generated name)
docker run -v /app/data nginx
Using --mount (explicit syntax)
# Named volume
docker run --mount type=volume,source=my-volume,target=/app/data nginx
# With options
docker run --mount type=volume,source=my-volume,target=/app/data,readonly nginx
Comparison
| Feature | -v / --volume | --mount |
|---|---|---|
| Syntax | Compact | Explicit |
| Create volume | Auto-creates if missing | Errors if missing |
| Clarity | Harder to read | Self-documenting |
| Options | Comma-separated | Key=value pairs |
Volume with Database Example
# Create volume for PostgreSQL data
docker volume create postgres-data
# Run PostgreSQL with the volume
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-v postgres-data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:15
# Data persists even if container is removed
docker rm -f postgres
# Start new container with same volume - data is still there!
docker run -d \
--name postgres-new \
-e POSTGRES_PASSWORD=secret \
-v postgres-data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:15
Managing Volumes
List Volumes
# List all volumes
docker volume ls
# Filter volumes
docker volume ls --filter "dangling=true" # Unused volumes
docker volume ls --filter "name=postgres" # By name pattern
# Format output
docker volume ls --format "{{.Name}}: {{.Driver}}"
Inspect Volumes
# Get volume details
docker volume inspect my-volume
# Get mount point
docker volume inspect -f '{{.Mountpoint}}' my-volume
Remove Volumes
# Remove a specific volume
docker volume rm my-volume
# Remove multiple volumes
docker volume rm vol1 vol2 vol3
# Force remove (even if in use - BE CAREFUL)
docker volume rm -f my-volume
# Remove all unused volumes
docker volume prune
# Remove with confirmation skip
docker volume prune -f
Volume Drivers
Volumes support different storage backends:
# Default local driver
docker volume create --driver local my-volume
# With driver options
docker volume create \
--driver local \
--opt type=nfs \
--opt o=addr=192.168.1.1,rw \
--opt device=:/path/to/dir \
nfs-volume
Common drivers:
- local: Default, stores on host filesystem
- nfs: Network File System
- azure: Azure File Storage
- aws: Amazon EBS
Sharing Volumes Between Containers
# Create shared volume
docker volume create shared-data
# Container 1: Writer
docker run -d \
--name writer \
-v shared-data:/data \
alpine sh -c "while true; do date >> /data/log.txt; sleep 1; done"
# Container 2: Reader
docker run -it --rm \
-v shared-data:/data:ro \
alpine tail -f /data/log.txt
Read-Only Volumes
Mount volumes as read-only for security:
# Using -v
docker run -v my-volume:/app/data:ro nginx
# Using --mount
docker run --mount type=volume,source=my-volume,target=/app/data,readonly nginx
Anonymous Volumes
Volumes without a name (Docker generates a random name):
# Create anonymous volume
docker run -v /app/data nginx
# Useful in Dockerfiles
# VOLUME /var/lib/mysql
# List shows random name
docker volume ls
# DRIVER VOLUME NAME
# local 8d7f6e5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0
Anonymous volumes are hard to reuse - prefer named volumes.
Volume in Dockerfile
Declare volumes in Dockerfile:
FROM postgres:15
# Declare volume mount point
VOLUME /var/lib/postgresql/data
# This creates an anonymous volume at runtime
# unless overridden by -v or --mount
Backup and Restore
Backup a Volume
# Create backup container that mounts volume and backup location
docker run --rm \
-v my-volume:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/my-volume-backup.tar.gz -C /source .
Restore a Volume
# Create new volume
docker volume create my-volume-restored
# Restore from backup
docker run --rm \
-v my-volume-restored:/target \
-v $(pwd):/backup:ro \
alpine tar xzf /backup/my-volume-backup.tar.gz -C /target
Key Takeaways
- Volumes persist data beyond container lifecycle
- Named volumes are managed by Docker in
/var/lib/docker/volumes - Use volumes for production data like databases
- Prefer
--mountsyntax for clarity - Volumes can be shared between containers
- Use read-only mounts for sensitive data
- Always back up important volumes
- Clean up unused volumes with
docker volume prune

