Containers need to talk to each other. They need to store data persistently. Docker networking and volumes solve these problems. Networks let containers communicate securely. Volumes keep data alive when containers die. In this lesson, you'll learn to connect containers and manage data like a pro.
1. Learning Objectives
By the end of this lesson, you will be able to:
- Create and manage Docker networks
- Connect containers to custom networks
- Understand network types (bridge, host, overlay, macvlan)
- Use volumes for persistent data
- Create bind mounts for development
- Backup and restore volumes
2. Why This Matters
Real-world scenario: Your database container dies. Without volumes, all data is lost. Your web container needs to talk to the database container. Without proper networking, they can't communicate. Networking and volumes are essential for production containers.
3. Core Concepts
Docker Networks
# List networks
docker network ls
# Inspect network
docker network inspect bridge
# Create custom network
docker network create mynetwork
# Create network with specific driver
docker network create --driver bridge my-bridge
docker network create --driver overlay my-overlay # Swarm mode
docker network create --driver macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 my-macvlan
# Remove network
docker network rm mynetwork
# Connect container to network
docker network connect mynetwork mycontainer
# Disconnect container from network
docker network disconnect mynetwork mycontainer
# Run container on specific network
docker run -d --name web --network mynetwork nginx
# Network types:
# bridge - Default, for single-host communication
# host - Uses host's network stack (no isolation)
# overlay - For multi-host (Swarm mode)
# macvlan - Assigns MAC addresses to containers
# none - No networking (isolated)
Docker network commands
Container Communication
# Without custom network (default bridge)
# Containers can't communicate by name
# Must use IP addresses
# Create custom network
docker network create app-network
# Run containers on same network
docker run -d --name web --network app-network nginx
docker run -d --name db --network app-network postgres
# Now containers can reach each other by name
# From web container: ping db
# From db container: ping web
# Test connectivity
docker exec web ping db
docker exec db ping web
# Multiple networks
docker network create frontend
docker network create backend
docker run -d --name web --network frontend nginx
docker run -d --name api --network frontend --network backend node
docker run -d --name db --network backend postgres
# web can talk to api (same frontend)
# api can talk to db (same backend)
# web cannot talk to db (different networks)
Container networking patterns
Docker Volumes (Persistent Data)
# Create named volume
docker volume create mydata
# List volumes
docker volume ls
# Inspect volume
docker volume inspect mydata
# Remove volume
docker volume rm mydata
# Run container with volume
docker run -d --name db -v mydata:/var/lib/postgresql/data postgres
# Named volume (recommended)
docker run -v myapp-data:/app/data myapp
# Anonymous volume (auto-generated name)
docker run -v /app/data myapp
# Bind mount (host directory)
docker run -v /home/user/data:/app/data myapp
# Read-only mount
docker run -v /home/user/config:/app/config:ro myapp
# Volume with options
docker volume create --driver local \
--opt type=nfs \
--opt device=:/path/to/nfs \
--opt o=addr=192.168.1.100,nolock,soft,rw \
nfs-volume
Docker volume commands
Volume Drivers
# Local driver (default)
docker volume create local-volume
# NFS driver
docker volume create --driver local \
--opt type=nfs \
--opt device=:/exports/data \
--opt o=addr=192.168.1.100,rw,nfsvers=4 \
nfs-data
# AWS EBS (via plugin)
docker plugin install rexray/ebs
docker volume create --driver rexray/ebs --opt size=10 ebs-volume
# Azure File (via plugin)
docker plugin install docker4x/azurefile
docker volume create --driver docker4x/azurefile azure-volume
# SSHFS (mount remote via SSH)
docker volume create --driver vieux/sshfs \
--opt sshcmd=user@server:/path \
--opt password=secret \
sshfs-volume
Volume drivers for different storage backends
Bind Mounts (Development)
# Bind mount absolute path
docker run -v /absolute/path:/app/data myapp
# Bind mount relative path
docker run -v $(pwd)/data:/app/data myapp
# Read-only bind mount
docker run -v $(pwd)/config:/app/config:ro myapp
# Docker Compose with bind mounts
# docker-compose.yml:
# services:
# app:
# volumes:
# - ./app:/app # Bind mount
# - /app/node_modules # Anonymous volume
# - app-data:/data # Named volume
# volumes:
# app-data:
# Develop with hot reload using bind mounts
docker run -p 3000:3000 -v $(pwd):/app -v /app/node_modules node npm run dev
Bind mounts for development
Backup and Restore Volumes
# Backup volume to tar file
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
tar czf /backup/mydata-backup.tar.gz -C /data .
# Restore volume from backup
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
tar xzf /backup/mydata-backup.tar.gz -C /data
# Backup database volume
docker run --rm -v postgres_data:/data -v $(pwd):/backup alpine \
tar czf /backup/postgres-$(date +%Y%m%d).tar.gz -C /data .
# Copy volume data to host
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
cp -r /data /backup/data
# Backup with compression
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
sh -c "cd /data && tar czf /backup/backup.tar.gz ."
# Restore from backup
mkdir restore
tar xzf backup.tar.gz -C restore/
Volume backup and restore
4. Complete Project: Production Network and Volume Setup
# docker-compose-production.yml
version: '3.8'
services:
# Web tier - public network
web:
image: nginx:alpine
networks:
- public
- internal
volumes:
- static_data:/usr/share/nginx/html
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- api
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 256M
# API tier - internal network only
api:
build: ./api
networks:
- internal
- backend
environment:
- DB_HOST=db
- REDIS_HOST=redis
volumes:
- uploads:/app/uploads
depends_on:
- db
- redis
deploy:
replicas: 2
resources:
limits:
cpus: '1'
memory: 512M
# Database - backend network
db:
image: postgres:15-alpine
networks:
- backend
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backup:/backup
deploy:
resources:
limits:
cpus: '2'
memory: 2G
# Redis cache
redis:
image: redis:7-alpine
networks:
- backend
command: redis-server --appendonly yes
volumes:
- redis_data:/data
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# Worker for background jobs
worker:
build: ./worker
networks:
- backend
- internal
environment:
- REDIS_URL=redis://redis:6379
- DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
volumes:
- uploads:/app/uploads
depends_on:
- db
- redis
deploy:
replicas: 2
# Monitoring - monitoring network
prometheus:
image: prom/prometheus
networks:
- monitoring
- internal
volumes:
- prometheus_data:/prometheus
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
grafana:
image: grafana/grafana
networks:
- monitoring
- internal
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
# Backup service
backup:
image: alpine
networks:
- backend
volumes:
- postgres_data:/source/postgres:ro
- redis_data:/source/redis:ro
- uploads:/source/uploads:ro
- ./backups:/backup
command: |
sh -c "
while true; do
tar czf /backup/backup-\$$(date +%Y%m%d-%H%M%S).tar.gz /source
sleep 86400
done"
# Networks with different isolation levels
networks:
public:
driver: bridge
driver_opts:
com.docker.network.bridge.name: public_net
internal:
driver: bridge
internal: true # No external access
backend:
driver: bridge
internal: true # Database network - completely isolated
monitoring:
driver: bridge
internal: true
# Volumes for persistent data
volumes:
postgres_data:
driver: local
driver_opts:
type: none
device: /mnt/data/postgres
o: bind
redis_data:
uploads:
static_data:
prometheus_data:
grafana_data:
# Deployment notes:
# 1. Public network: External users reach web tier
# 2. Internal network: API and monitoring (web can reach API)
# 3. Backend network: Database tier, completely isolated from web
# 4. All volumes are persisted on host storage
Production network isolation and volume setup
5. Common Errors & Solutions
6. Summary Checklist
7. Next Steps
Next lesson: Docker Lesson 5.5: Docker Best Practices & Security
Comments (0)
This is exactly what I needed! The initContainer approach solved our migration issues completely. Thanks for the detailed guide!
ReplyLeave a Comment