How to Use Volumes in Docker Compose for Data Persistence
In
docker-compose.yml, use the volumes key to define storage that persists data outside containers. You can mount host directories or named volumes inside containers by specifying paths under services and volumes sections.Syntax
The volumes section in docker-compose.yml defines named volumes or host paths. Under each service, you specify volumes to mount these into container paths.
- Named volume: A volume managed by Docker, declared under
volumes:at root. - Host path: A directory on your machine, mounted directly into the container.
- Container path: The location inside the container where the volume is mounted.
yaml
version: '3.8'
services:
service_name:
image: example-image
volumes:
- volume_name:/container/path
- ./host/path:/container/path
volumes:
volume_name: {}Example
This example shows a web service using a named volume to persist database files and a host directory to serve static files. The named volume keeps data safe even if the container is removed.
yaml
version: '3.8' services: web: image: nginx:alpine volumes: - static_content:/usr/share/nginx/html - ./config/nginx.conf:/etc/nginx/nginx.conf:ro db: image: postgres:15 volumes: - db_data:/var/lib/postgresql/data volumes: static_content: {} db_data: {}
Output
docker-compose up -d
# Containers start with volumes mounted
# Data in db_data persists across container restarts
# Static files served from host ./config directory
Common Pitfalls
- Forgetting to declare named volumes: Named volumes must be listed under the
volumes:root key or Docker will create anonymous volumes. - Incorrect host path: Relative paths are relative to the
docker-compose.ymllocation; wrong paths cause errors or empty mounts. - Permission issues: Host directory permissions can block container access; ensure proper read/write rights.
- Using
latesttag: Avoid usinglatestfor images to prevent unexpected changes affecting volumes.
yaml
version: '3.8'
services:
app:
image: alpine
volumes:
- missing_volume:/data
volumes:
# missing_volume is not declared here, Docker creates anonymous volume instead
# Correct way:
volumes:
missing_volume: {}Quick Reference
Remember these tips when using volumes in Docker Compose:
- Define named volumes under
volumes:at root. - Mount volumes under each service with
service_name:→volumes:. - Use
host_path:container_pathfor host directory mounts. - Use
volume_name:container_pathfor named volumes. - Use
:rosuffix for read-only mounts.
Key Takeaways
Define volumes under the root
volumes: key to create named volumes.Mount volumes inside services using
volumes: with volume_name:container_path or host_path:container_path syntax.Use named volumes to persist data beyond container life and host paths to share files with the host system.
Check paths and permissions carefully to avoid mount errors or access issues.
Add
:ro to mounts to make them read-only inside containers.