docker-compose-patterns/references/volumes-and-networks.md
Version 3e1cbd179989 · Apache-2.0. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.
← Return to resource and package checksum
Volumes and Networks
Volume types
Named volumes
Use named volumes for data that must persist across container recreations:
services:
db:
image: postgres:17
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
Named volumes are managed by Docker. They survive docker compose down (but not docker compose down -v, which deletes them and their data irreversibly). Never run down -v to work around a startup or connectivity problem — get explicit user confirmation first.
Bind mounts
Use bind mounts to sync host directories into containers. Appropriate for development-time source code mounting only:
services:
web:
build: .
volumes:
- ./src:/app/src
Do not use bind mounts for database data — they cause permission issues and poor performance on macOS and Windows.
Anonymous volumes
Avoid anonymous volumes (volumes with no name and no host path). They are hard to track and clean up. Always use named volumes.
tmpfs mounts
Use tmpfs for ephemeral scratch data that should not persist:
services:
app:
image: myapp:1.0.0
tmpfs:
- /tmp
- /app/cache
Volume mount flags
- Use
:roto mount volumes as read-only when the container should not write to them. - Use
:cachedor:delegatedon macOS only when performance requires it and data consistency tradeoffs are acceptable. Prefer Compose Watch (develop.watch) over bind mounts with performance flags.
Volume patterns
Excluding node_modules from bind mounts
When bind-mounting a Node.js project, exclude node_modules with an anonymous volume to prevent host dependencies from overwriting container dependencies:
services:
web:
build: .
volumes:
- ./:/app
- /app/node_modules
This mounts the project root but keeps the container's own node_modules intact.
Sharing data between services
Use a named volume to share files between services:
services:
generator:
image: myapp:1.0.0
volumes:
- shared-data:/output
consumer:
image: nginx:1.27
volumes:
- shared-data:/usr/share/nginx/html:ro
volumes:
shared-data:
Networks
Default network
Compose creates a default network for each project. All services join it automatically. Services can reach each other by service name as the hostname. For most single-application stacks, the default network is sufficient.
Custom networks for isolation
Use custom networks when you need to isolate groups of services:
services:
web:
image: myapp:1.0.0
networks:
- frontend
- backend
db:
image: postgres:17
networks:
- backend
proxy:
image: nginx:1.27
networks:
- frontend
networks:
frontend:
backend:
In this example, proxy cannot reach db directly because they share no network. web bridges both.
External networks
Use external: true to reference a network created outside this Compose file:
networks:
shared:
external: true
name: my-shared-network
This is useful when multiple Compose projects need to communicate.
Network aliases
Use aliases to give a service additional hostnames on a specific network:
services:
db:
image: postgres:17
networks:
backend:
aliases:
- database
- postgres
Other services on the backend network can reach this service as db, database, or postgres.