Docker Compose Volumes
Persist data and share files between host and containers.
Volume Types
Named Volumes
services:
db:
image: postgres
volumes:
- postgres-data:/var/lib/postgresql/data
redis:
image: redis
volumes:
- redis-data:/data
volumes:
postgres-data:
redis-data:Bind Mounts
services:
app:
volumes:
# Development: mount source code
- ./src:/app/src
- ./config:/app/config:ro # Read-only
nginx:
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/htmlAnonymous Volumes
services:
app:
volumes:
- /app/node_modules # Preserve container's node_modulesVolume Configuration
volumes:
db-data:
driver: local
# With options
app-data:
driver: local
driver_opts:
type: none
device: /data/app
o: bind
# External volume (pre-existing)
shared-data:
external: true
name: my-shared-volumeDevelopment vs Production
Development
# docker-compose.dev.yml
services:
app:
volumes:
- .:/app # Full source mount
- /app/node_modules # Exclude node_modules
command: npm run devProduction
# docker-compose.prod.yml
services:
app:
volumes:
- app-logs:/app/logs # Only logs
- app-uploads:/app/uploads # User uploads
volumes:
app-logs:
app-uploads:Common Patterns
Database with Initialization
services:
db:
image: postgres:16
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
mysql:
image: mysql:8
volumes:
- mysql-data:/var/lib/mysql
- ./init:/docker-entrypoint-initdb.d:ro
volumes:
postgres-data:
mysql-data:Sharing Data Between Services
services:
app:
volumes:
- shared-uploads:/app/uploads
nginx:
volumes:
- shared-uploads:/usr/share/nginx/html/uploads:ro
volumes:
shared-uploads:Config Files
services:
nginx:
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs:roVolume Commands
# List volumes
docker volume ls
# Inspect volume
docker volume inspect project_postgres-data
# Remove volumes with compose
docker compose down -v
# Backup volume
docker run --rm -v project_db-data:/data -v $(pwd):/backup \
alpine tar cvf /backup/db-backup.tar /data
# Restore volume
docker run --rm -v project_db-data:/data -v $(pwd):/backup \
alpine tar xvf /backup/db-backup.tar -C /Complete Example
services:
app:
build: .
volumes:
- app-uploads:/app/uploads
- app-logs:/app/logs
- ./config/app.json:/app/config.json:ro
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d:ro
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- app-uploads:/var/www/uploads:ro
- nginx-cache:/var/cache/nginx
volumes:
app-uploads:
app-logs:
db-data:
nginx-cache:
secrets:
db_password:
file: ./secrets/db_password.txt - docker compose
- volumes
- persistence
- bind mounts