Volumes
What are Docker Volumes?¶
Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. Unlike bind mounts, volumes are completely managed by Docker.
Why Use Volumes?¶
- Data persistence - Data survives container removal
- Sharing data - Multiple containers can share the same volume
- Performance - Better performance than bind mounts on Mac/Windows
- Backups - Easier to backup and migrate
- Remote storage - Can be hosted on remote systems or cloud
Types of Mounts¶
Volumes (Recommended)¶
Managed by Docker, stored in Docker's storage directory.
# Create volume
docker volume create my-data
# Use volume
docker run -v my-data:/app/data nginx
Bind Mounts¶
Mount a file or directory from host into container.
# Mount current directory
docker run -v $(pwd):/app nginx
# Mount specific file
docker run -v /path/on/host:/path/in/container nginx
tmpfs Mounts¶
Stored in host memory only, not persisted.
# Use tmpfs
docker run --tmpfs /app/cache nginx
Comparison¶
| Feature | Volumes | Bind Mounts | tmpfs |
|---|---|---|---|
| Managed by Docker | Yes | No | No |
| Location | Docker directory | Anywhere on host | RAM |
| Performance | Good | Varies | Excellent |
| Persist after container removed | Yes | Yes | No |
| Can share between containers | Yes | Yes | No |
| Backup/restore | Easy | Manual | Not possible |
Working with Volumes¶
Create Volume¶
# Create volume
docker volume create my-volume
# Create with driver options
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=192.168.1.1,rw \
--opt device=:/path/to/dir \
my-nfs-volume
List Volumes¶
# List all volumes
docker volume ls
# Filter by name
docker volume ls --filter name=my-volume
# Filter dangling volumes
docker volume ls --filter dangling=true
Inspect Volume¶
# View volume details
docker volume inspect my-volume
# View mount point
docker volume inspect -f '{{.Mountpoint}}' my-volume
Remove Volume¶
# Remove specific volume
docker volume rm my-volume
# Remove all unused volumes
docker volume prune
# Remove with force
docker volume rm -f my-volume
Using Volumes with Containers¶
Named Volume¶
# Create and use in one command
docker run -v my-data:/app/data nginx
# Using --mount (more explicit)
docker run --mount source=my-data,target=/app/data nginx
Anonymous Volume¶
Created automatically, harder to reference:
# Docker creates random volume name
docker run -v /app/data nginx
Read-Only Volume¶
# Mount as read-only
docker run -v my-data:/app/data:ro nginx
# Using --mount
docker run --mount source=my-data,target=/app/data,readonly nginx
Bind Mount¶
# Mount host directory
docker run -v $(pwd)/data:/app/data nginx
# Using --mount
docker run --mount type=bind,source=$(pwd)/data,target=/app/data nginx
Volume Examples¶
Persist Database Data¶
# Create volume
docker volume create postgres-data
# Run PostgreSQL with volume
docker run -d \
--name postgres \
-v postgres-data:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=secret \
postgres:13
# Data persists even after container removal
docker rm -f postgres
docker run -d --name postgres -v postgres-data:/var/lib/postgresql/data postgres:13
Share Data Between Containers¶
# Create shared volume
docker volume create shared-data
# Writer container
docker run -d --name writer \
-v shared-data:/data \
alpine sh -c "while true; do date >> /data/log.txt; sleep 1; done"
# Reader container
docker run -d --name reader \
-v shared-data:/data:ro \
alpine tail -f /data/log.txt
Development with Bind Mounts¶
# Mount source code for live reloading
docker run -d \
--name dev-app \
-v $(pwd)/src:/app/src \
-p 3000:3000 \
node:16 \
npm run dev
Backup Volume¶
# Backup volume to tar file
docker run --rm \
-v my-data:/data \
-v $(pwd):/backup \
alpine \
tar czf /backup/data-backup.tar.gz /data
# Restore from backup
docker run --rm \
-v my-data:/data \
-v $(pwd):/backup \
alpine \
tar xzf /backup/data-backup.tar.gz -C /
Docker Compose with Volumes¶
Named Volumes¶
version: '3.8'
services:
db:
image: postgres
volumes:
- postgres-data:/var/lib/postgresql/data
app:
build: .
volumes:
- app-data:/app/data
volumes:
postgres-data:
app-data:
Bind Mounts¶
version: '3.8'
services:
app:
build: .
volumes:
- ./src:/app/src # Bind mount
- ./config:/app/config # Bind mount
- node_modules:/app/node_modules # Named volume
volumes:
node_modules:
Volume Configuration¶
volumes:
postgres-data:
driver: local
driver_opts:
type: none
o: bind
device: /path/on/host
nfs-data:
driver: local
driver_opts:
type: nfs
o: addr=192.168.1.1,rw
device: ":/path/to/dir"
External Volumes¶
volumes:
existing-volume:
external: true # Use existing volume
Volume Use Cases¶
Development¶
services:
app:
volumes:
# Live reload - changes reflect immediately
- ./src:/app/src
# Preserve node_modules from image
- /app/node_modules
# Share config
- ./config:/app/config:ro
Production Database¶
services:
postgres:
image: postgres:13
volumes:
# Persist data
- postgres-data:/var/lib/postgresql/data
# Custom config
- ./postgres.conf:/etc/postgresql/postgresql.conf:ro
# Init scripts
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
volumes:
postgres-data:
driver: local
Logs and Monitoring¶
services:
app:
volumes:
# Application logs
- ./logs:/app/logs
nginx:
volumes:
# Web server logs
- ./logs/nginx:/var/log/nginx
Volume Drivers¶
Docker supports various volume drivers:
Local¶
Default driver, stores data on host:
docker volume create --driver local my-volume
NFS¶
Network File System:
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=192.168.1.1,rw \
--opt device=:/path/to/dir \
nfs-volume
Cloud Storage¶
Various plugins for AWS EBS, Azure File Storage, Google Cloud Storage, etc.
Volume Best Practices¶
For Development¶
- Use bind mounts for source code (live reload)
- Use named volumes for dependencies (node_modules)
- Use bind mounts for config files
- Mount as read-only when possible
services:
app:
volumes:
- ./src:/app/src # Source code
- node_modules:/app/node_modules # Dependencies
- ./config.yml:/app/config.yml:ro # Config (read-only)
For Production¶
- Use named volumes for databases
- Use named volumes for uploaded files
- Use read-only mounts for config
- Regular backups of volumes
- Use volume labels for organization
services:
db:
volumes:
- postgres-data:/var/lib/postgresql/data
- ./postgres.conf:/etc/postgresql/postgresql.conf:ro
volumes:
postgres-data:
labels:
app: myapp
environment: production
General Best Practices¶
- Name your volumes - Easier to manage than anonymous volumes
- Document volume contents - What data is stored where
- Regular backups - Automate volume backups
- Clean up - Remove unused volumes regularly
- Don't store secrets - Use Docker secrets or environment variables
- Consider performance - Volumes perform better than bind mounts
- Use specific paths - Avoid mounting entire root directories
Troubleshooting Volumes¶
View Volume Contents¶
# Run temporary container to inspect volume
docker run --rm -v my-data:/data alpine ls -la /data
Check Volume Size¶
# Get mountpoint
docker volume inspect -f '{{.Mountpoint}}' my-volume
# Check size (Linux)
sudo du -sh /var/lib/docker/volumes/my-volume/_data
Permission Issues¶
# Check ownership
docker run --rm -v my-data:/data alpine ls -ln /data
# Fix ownership (if needed)
docker run --rm -v my-data:/data alpine chown -R 1000:1000 /data
Find Containers Using Volume¶
# List containers using volume
docker ps -a --filter volume=my-volume
Skill++¶
Docker volumes can be stored on remote hosts or cloud providers, allowing containers to access shared data across multiple machines!