Docker Networking
Docker networking enables containers to communicate with each other and the outside world. Understanding Docker networking is essential for building multi-container applications and microservices. This guide covers everything from basic networking concepts to advanced network configurations.
If you’re new to Docker, you might want to start with our Docker basics and Dockerfile guides first.
Docker Network Fundamentals
Docker provides several networking drivers that determine how containers communicate.
Network Drivers Overview
# View available network drivers
docker network ls
# Default networks created by Docker
docker network ls --filter driver=bridge
docker network ls --filter driver=host
docker network ls --filter driver=overlayCommon Network Drivers:
- Bridge: Default driver for standalone containers
- Host: Remove network isolation, use host’s network directly
- Overlay: Enables multi-host communication for swarm clusters
- Macvlan: Assign MAC addresses to containers
- None: Disable networking for containers
Bridge Network (Default)
# Create a custom bridge network
docker network create my-app-network
# Inspect network details
docker network inspect my-app-network
# Run containers with custom network
docker run -d --name web-server --network my-app-network nginx:alpine
docker run -d --name database --network my-app-network postgres:13
# Containers can communicate using names as hostnames
docker exec web-server ping database# docker-compose.yml version with custom network
version: '3.8'
services:
web:
image: nginx:alpine
container_name: web-server
networks:
- app-network
ports:
- "8080:80"
database:
image: postgres:13
container_name: database
environment:
POSTGRES_PASSWORD: secret
networks:
- app-network
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
postgres_data:Advanced Network Configuration
Custom Network with Specific Subnet
# Create network with custom subnet and gateway
docker network create \
--driver bridge \
--subnet=192.168.100.0/24 \
--gateway=192.168.100.1 \
--ip-range=192.168.100.128/25 \
my-custom-network
# Run container with specific IP
docker run -d \
--name static-ip-container \
--network my-custom-network \
--ip 192.168.100.50 \
nginx:alpine
# Verify IP assignment
docker inspect static-ip-container | grep IPAddressHost Networking
# Use host networking (container shares host's network stack)
docker run -d \
--name host-network-app \
--network host \
nginx:alpine
# The container listens directly on host port 80
curl http://localhost:80Macvlan Networking
# Create macvlan network
docker network create \
--driver macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
macvlan-net
# Run container with macvlan
docker run -d \
--name macvlan-container \
--network macvlan-net \
nginx:alpineMulti-Container Application Networks
Complex Multi-Service Setup
# docker-compose.yml for microservices application
version: '3.8'
services:
# Frontend service
frontend:
build: ./frontend
container_name: frontend-app
networks:
- frontend-network
- backend-network
ports:
- "3000:3000"
depends_on:
- api-gateway
environment:
REACT_APP_API_URL: http://api-gateway:8080
# API Gateway
api-gateway:
build: ./api-gateway
container_name: api-gateway
networks:
- backend-network
- database-network
ports:
- "8080:8080"
depends_on:
- user-service
- product-service
- order-service
environment:
USER_SERVICE_URL: http://user-service:8001
PRODUCT_SERVICE_URL: http://product-service:8002
ORDER_SERVICE_URL: http://order-service:8003
# Microservices
user-service:
build: ./user-service
container_name: user-service
networks:
- database-network
environment:
DATABASE_URL: postgres://user:password@user-db:5432/users
REDIS_URL: redis://redis:6379
depends_on:
- user-db
- redis
product-service:
build: ./product-service
container_name: product-service
networks:
- database-network
environment:
DATABASE_URL: postgres://product:password@product-db:5432/products
REDIS_URL: redis://redis:6379
depends_on:
- product-db
- redis
order-service:
build: ./order-service
container_name: order-service
networks:
- database-network
environment:
DATABASE_URL: postgres://order:password@order-db:5432/orders
REDIS_URL: redis://redis:6379
depends_on:
- order-db
- redis
# Databases
user-db:
image: postgres:13
container_name: user-db
networks:
- database-network
environment:
POSTGRES_DB: users
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- user_db_data:/var/lib/postgresql/data
product-db:
image: postgres:13
container_name: product-db
networks:
- database-network
environment:
POSTGRES_DB: products
POSTGRES_USER: product
POSTGRES_PASSWORD: password
volumes:
- product_db_data:/var/lib/postgresql/data
order-db:
image: postgres:13
container_name: order-db
networks:
- database-network
environment:
POSTGRES_DB: orders
POSTGRES_USER: order
POSTGRES_PASSWORD: password
volumes:
- order_db_data:/var/lib/postgresql/data
# Cache
redis:
image: redis:7-alpine
container_name: redis
networks:
- database-network
volumes:
- redis_data:/data
# Load Balancer
nginx-lb:
image: nginx:alpine
container_name: nginx-lb
networks:
- frontend-network
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/ssl:/etc/nginx/ssl
depends_on:
- frontend
networks:
frontend-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
backend-network:
driver: bridge
ipam:
config:
- subnet: 172.21.0.0/24
database-network:
driver: bridge
internal: true # Internal network (no external access)
ipam:
config:
- subnet: 172.22.0.0/24
volumes:
user_db_data:
product_db_data:
order_db_data:
redis_data:Network Security and Isolation
Internal Networks
# Create internal network (no external access)
docker network create \
--driver bridge \
--internal \
secure-backend
# Run backend service on internal network
docker run -d \
--name backend-api \
--network secure-backend \
my-backend-app
# Frontend can connect to backend through multiple networks
docker run -d \
--name frontend-app \
--network my-app-network \
--network secure-backend \
my-frontend-appNetwork Aliases and DNS
version: '3.8'
services:
app:
image: my-app
networks:
app-network:
aliases:
- api
- backend
- app.example.com
worker:
image: my-worker
networks:
app-network:
aliases:
- worker
- processor
networks:
app-network:
driver: bridgePort Mapping and Exposure
# Different port mapping strategies
# Map container port 3000 to host port 8080
docker run -d -p 8080:3000 my-app
# Map to all interfaces (default)
docker run -d -p 0.0.0.0:8080:3000 my-app
# Map to localhost only
docker run -d -p 127.0.0.1:8080:3000 my-app
# Random host port
docker run -d -p 3000 my-app
# Map multiple ports
docker run -d -p 8080:3000 -p 9090:9090 my-app
# Port ranges
docker run -d -p 8000-8010:3000-3010 my-appOverlay Networks for Swarm
Docker Swarm Setup
# Initialize Docker Swarm
docker swarm init --advertise-addr <MANAGER-IP>
# Create overlay network
docker network create \
--driver overlay \
--attachable \
--subnet=10.0.9.0/24 \
my-overlay-network
# Deploy services with overlay network
docker service create \
--name web-service \
--network my-overlay-network \
--replicas 3 \
nginx:alpine
docker service create \
--name database-service \
--network my-overlay-network \
--replicas 1 \
postgres:13# docker-stack.yml for Swarm deployment
version: '3.8'
services:
web:
image: nginx:alpine
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
networks:
- webnet
ports:
- "80:80"
database:
image: postgres:13
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
environment:
POSTGRES_PASSWORD: secret
networks:
- dbnet
volumes:
- db_data:/var/lib/postgresql/data
backend:
image: my-backend-app
deploy:
replicas: 2
networks:
- webnet
- dbnet
environment:
DATABASE_URL: postgres://postgres:secret@database:5432/mydb
networks:
webnet:
driver: overlay
attachable: true
dbnet:
driver: overlay
internal: true
volumes:
db_data:Network Troubleshooting
Common Network Issues
# Check container network settings
docker inspect <container-name> | grep -A 20 "NetworkSettings"
# Test connectivity between containers
docker exec container1 ping container2
docker exec container1 nslookup container2
# Check network interfaces inside container
docker exec container1 ip addr show
# Monitor network traffic
docker exec container1 tcpdump -i eth0
# Check DNS resolution
docker exec container1 cat /etc/resolv.conf
# Test port connectivity
docker exec container1 nc -zv database 5432Network Debugging Tools
# Install debugging tools in container
docker run -it --rm \
--network my-app-network \
nicolaka/netshoot \
ping database
# Use network debugging container
docker run -it --rm \
--network container:target-container \
nicolaka/netshoot \
tcpdump -i eth0
# Connect container to multiple networks for debugging
docker network connect my-app-network debug-container
docker network connect secure-backend debug-containerHealth Checks and Network Dependencies
version: '3.8'
services:
web:
image: nginx:alpine
depends_on:
api:
condition: service_healthy
networks:
- app-network
api:
image: my-api
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- app-network
- database-network
database:
image: postgres:13
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- database-network
networks:
app-network:
driver: bridge
database-network:
driver: bridge
internal: truePerformance Optimization
Network Performance Tuning
# Optimize network settings
docker network create \
--driver bridge \
--opt com.docker.network.bridge.enable_icc=true \
--opt com.docker.network.bridge.enable_ip_masquerade=true \
--opt com.docker.network.driver.mtu=1500 \
performance-network
# Container network settings
docker run -d \
--name performance-app \
--network performance-network \
--network-alias api \
--dns 8.8.8.8 \
--dns-search example.com \
my-performance-appLoad Balancing with Nginx
# nginx.conf for load balancing
events {
worker_connections 1024;
}
http {
upstream backend_servers {
server backend1:8000 weight=3 max_fails=3 fail_timeout=30s;
server backend2:8000 weight=2 max_fails=3 fail_timeout=30s;
server backend3:8000 weight=1 backup;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
}
}# docker-compose.yml with load balancer
version: '3.8'
services:
nginx-lb:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- backend1
- backend2
- backend3
networks:
- frontend-network
- backend-network
backend1:
image: my-backend-app
environment:
INSTANCE_ID: 1
networks:
- backend-network
backend2:
image: my-backend-app
environment:
INSTANCE_ID: 2
networks:
- backend-network
backend3:
image: my-backend-app
environment:
INSTANCE_ID: 3
networks:
- backend-network
networks:
frontend-network:
driver: bridge
backend-network:
driver: bridge
internal: trueSecurity Best Practices
Network Segmentation
# Create network tiers
docker network create frontend-tier --subnet 172.20.0.0/24
docker network create application-tier --subnet 172.21.0.0/24 --internal
docker network create data-tier --subnet 172.22.0.0/24 --internal
# Deploy services to appropriate tiers
docker run -d --name web --network frontend-tier nginx
docker run -d --name api --network application-tier my-api
docker run -d --name database --network data-tier postgres
# Connect specific containers between tiers
docker network connect application-tier webNetwork Policies
# Use network policies for security
version: '3.8'
services:
frontend:
image: nginx:alpine
networks:
- frontend-only
ports:
- "80:80"
backend:
image: my-backend
networks:
- frontend-backend
- backend-only
database:
image: postgres:13
networks:
- backend-only
environment:
POSTGRES_PASSWORD: secure_password
networks:
frontend-only:
driver: bridge
frontend-backend:
driver: bridge
backend-only:
driver: bridge
internal: trueMonitoring Network Traffic
Network Monitoring Tools
# Monitor network statistics
docker stats --no-stream --format "table {{.Container}}\t{{.NetIO}}"
# Inspect network traffic
docker run -it --rm \
--network container:my-container \
alpine /bin/sh -c "apk add --no-cache tcpdump && tcpdump -i eth0"
# Network bandwidth monitoring
docker run -it --rm \
--network container:my-container \
nicolaka/netshoot \
ifstat -i eth0 1This Docker networking guide covers everything you need to build robust, secure, and scalable containerized applications. Practice these concepts with real multi-container applications to master Docker networking.
For more Docker tutorials, check out our guides on multi-stage builds and Docker Compose.
The Docker Networking Documentation provides comprehensive technical details, and the Docker Best Practices guide offers valuable insights for production deployments.