Docker Compose — Networks and Volumes
Why Networks and Volumes Matter
Networks enable services to communicate with each other. Volumes persist data beyond the container lifecycle. Together they form the backbone of multi-service applications in Docker Compose. Without understanding networks and volumes, your containers cannot talk to each other and your data disappears when containers restart.
Why this matters for your career:
- Networking misconfiguration is a top cause of Docker issues
- Data persistence is essential for databases, caches, and user uploads
- Understanding Docker networking is required for Kubernetes networking
- Volume management is key for backups and data migration
Docker Compose Networks
By default, Docker Compose creates a single network for all services defined in the compose file. Services can reach each other by service name (which acts as a DNS hostname).
Default Network
version: "3.9"
services:
web:
image: nginx
# Can reach: db, redis by hostname
db:
image: postgres
redis:
image: redis
# Docker Compose creates a network called: project_default
Inside the web container, you can connect to the database using the hostname db and the port 5432 (inside the container).
Custom Networks
version: "3.9"
services:
frontend:
image: nginx
networks:
- frontend_net
- backend_net
api:
image: my-api
networks:
- backend_net
- database_net
db:
image: postgres
networks:
- database_net
networks:
frontend_net:
driver: bridge
backend_net:
driver: bridge
database_net:
driver: bridge
This creates three isolated networks:
- frontend_net: frontend + api (frontend can reach api)
- backend_net: api + frontend (shared)
- database_net: api + db (api can reach db, frontend cannot)
Network isolation improves security by limiting which services can communicate.
Network Drivers
| Driver | Isolation | Use Case | |--------|-----------|----------| | bridge | Per-network | Default, single-host | | host | None (uses host network) | Performance-critical, single service | | overlay | Multi-host | Docker Swarm, multi-node | | macvlan | MAC address per container | Legacy apps needing direct network access | | none | Complete isolation | Security testing, standalone services |
Docker Compose Volumes
Volumes persist data generated by containers. They survive container restarts, updates, and deletions.
Named Volumes
version: "3.9"
services:
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7
volumes:
- redis_data:/data
volumes:
pgdata:
redis_data:
Named volumes are managed by Docker and stored in /var/lib/docker/volumes/. They are the preferred way to persist data.
Bind Mounts
Bind mounts map a host directory into the container:
services:
web:
image: nginx
volumes:
- ./html:/usr/share/nginx/html:ro # Read-only mount
- ./nginx.conf:/etc/nginx/nginx.conf:ro
app:
build: .
volumes:
- .:/app # Development hot-reload
- /app/node_modules # Exclude node_modules from mount
Bind mounts are ideal for development (hot-reload) and configuration files. They are not recommended for production database storage.
tmpfs Mounts
services:
cache:
image: redis:7
tmpfs:
- /data # Temporary, in-memory storage
tmpfs mounts are stored in memory only. They are fast but data is lost when the container stops. Use for caches and temporary files.
Volume Operations
# List volumes
docker volume ls
# Inspect a volume
docker volume inspect pgdata
# Remove unused volumes
docker volume prune
# Backup a volume
docker run --rm -v pgdata:/source -v $(pwd):/backup alpine \
tar czf /backup/pgdata-backup.tar.gz -C /source .
# Restore a volume
docker run --rm -v pgdata:/target -v $(pwd):/backup alpine \
tar xzf /backup/pgdata-backup.tar.gz -C /target
Network + Volume Complete Example
version: "3.9"
services:
app:
build: .
ports:
- "3000:3000"
networks:
- app_net
- db_net
volumes:
- .:/app # dev hot-reload
- uploads:/app/uploads
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
networks:
- db_net
volumes:
- pgdata:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: ${DB_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
networks:
- app_net
volumes:
- redis_data:/data
tmpfs:
- /tmp
networks:
app_net:
db_net:
volumes:
pgdata:
redis_data:
uploads:
This setup provides:
- app can reach redis (same app_net) and db (connected to both)
- db is isolated on db_net (only app can reach it)
- Database data persists via
pgdatanamed volume - User uploads persist via
uploadsnamed volume - Redis data persists, but /tmp is temporary (tmpfs)
- App waits for db to be healthy before starting
Volume Driver Options
| Driver | Description | Use Case | |--------|-------------|----------| | local | Default, stored on host | General purpose | | nfs | Network File System | Shared storage across hosts | | cloudstor | AWS EBS, Azure Disk | Cloud storage integration | | cifs | Samba/CIFS | Windows file shares | | tmpfs | In-memory | Caches, temporary data |
Best Practices
| Practice | Reason | |----------|--------| | Use named volumes for databases | Data survives container restart | | Use bind mounts for development | Live code reload | | Use bind mounts for config files | Easy configuration changes | | Isolate networks by function | Security — limit which services can talk | | Always set healthcheck on databases | Other services wait for db readiness | | Never store secrets in bind mounts | Secrets in files may be committed to git | | Backup named volumes regularly | Data loss prevention | | Use tmpfs for caches | Speed, no disk wear |
Summary
Networks and volumes are essential for multi-service Docker Compose applications. Networks control which services can communicate, and volumes persist data beyond container lifetimes. Proper network isolation improves security, while proper volume configuration ensures data durability.
Key takeaways:
- Default network: all services can communicate by hostname
- Custom networks provide isolation between service groups
- Named volumes persist data (managed by Docker)
- Bind mounts share host directories with containers
- tmpfs mounts are in-memory (fast, ephemeral)
- Network drivers: bridge (default), host, overlay, macvlan
- Use healthchecks to manage startup order
- Back up named volumes regularly
What's Next: Deploy to VPS
The next chapter covers deploying Docker Compose applications to a VPS — using docker-compose in production, reverse proxy with Nginx, SSL certificates, and monitoring.