Master Docker networking concepts including bridge networks, host networking, overlay networks, and container communication patterns for microservices architectures.
Docker networking enables containers to communicate with each other, the host, and external networks. Understanding Docker networking is essential for building microservices architectures, securing container communication, and deploying multi-container applications. This lesson covers the different network drivers, how to create custom networks, container DNS and service discovery, and best practices for production network configurations.
Docker uses a pluggable networking architecture with different drivers for various use cases:
Network Drivers Overview:
1┌─────────────────────────────────────────────────────────────────┐
2│ Docker Network Drivers │
3├─────────────────────────────────────────────────────────────────┤
4│ │
5│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
6│ │ Bridge │ │ Host │ │ Overlay │ │ macvlan │ │
7│ │ │ │ │ │ │ │ │ │
8│ │ Default │ │ No NAT │ │ Multi- │ │ Physical │ │
9│ │ NAT │ │ Direct │ │ host │ │ network │ │
10│ │ Isolated │ │ access │ │ Swarm │ │ access │ │
11│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
12│ │
13│ ┌──────────┐ ┌──────────┐ │
14│ │ None │ │ IPvlan │ │
15│ │ │ │ │ │
16│ │ No │ │ L2/L3 │ │
17│ │ network │ │ routing │ │
18│ └──────────┘ └──────────┘ │
19│ │
20└─────────────────────────────────────────────────────────────────┘Bridge Network (Default):
1# Default bridge network
2docker network inspect bridge
3
4# Containers on default bridge:
5# - Can communicate via IP addresses
6# - Cannot use container names for DNS
7# - NAT for external connectivity
8
9# View bridge interfaces
10ip link show docker0Default Networks:
1# List all networks
2docker network ls
3
4# Output:
5# NETWORK ID NAME DRIVER SCOPE
6# abc123def456 bridge bridge local
7# def456abc789 host host local
8# 789abc123def none null localNetwork Driver Comparison:
| Driver | Use Case | Isolation | DNS | Multi-Host |
|--------|----------|-----------|-----|------------|
| bridge | Default, single host | High | Custom only | No |
| host | Performance critical | None | Host | No |
| overlay | Swarm services | High | Yes | Yes |
| macvlan | Legacy integration | Physical | No | No |
| none | Security/custom | Total | No | No |
Custom bridge networks provide DNS resolution and better isolation:
Creating Custom Networks:
1# Create a custom bridge network
2docker network create myapp-network
3
4# Create with options
5docker network create \
6 --driver bridge \
7 --subnet 172.20.0.0/16 \
8 --ip-range 172.20.240.0/20 \
9 --gateway 172.20.0.1 \
10 --opt "com.docker.network.bridge.name"="myapp-br" \
11 --label project=myapp \
12 myapp-network
13
14# Create with IPv6
15docker network create \
16 --ipv6 \
17 --subnet 2001:db8::/64 \
18 myapp-ipv6Using Custom Networks:
1# Run container on custom network
2docker run -d \
3 --name web \
4 --network myapp-network \
5 nginx:alpine
6
7# Connect running container to network
8docker network connect myapp-network existing-container
9
10# Disconnect from network
11docker network disconnect myapp-network container-name
12
13# Assign specific IP
14docker run -d \
15 --name db \
16 --network myapp-network \
17 --ip 172.20.0.10 \
18 postgres:15-alpineDNS Resolution in Custom Networks:
1# Containers can reach each other by name
2docker run -d --name api --network myapp-network alpine sleep 3600
3docker run -d --name db --network myapp-network alpine sleep 3600
4
5# Test DNS resolution
6docker exec api ping -c 2 db
7# PING db (172.20.0.3): 56 data bytes
8# 64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.123 ms
9
10# Custom DNS options
11docker run -d \
12 --name app \
13 --network myapp-network \
14 --dns 8.8.8.8 \
15 --dns-search example.com \
16 alpineNetwork Aliases:
1# Create container with aliases
2docker run -d \
3 --name web1 \
4 --network myapp-network \
5 --network-alias webserver \
6 --network-alias web \
7 nginx:alpine
8
9# Another container with same alias (load balancing)
10docker run -d \
11 --name web2 \
12 --network myapp-network \
13 --network-alias webserver \
14 nginx:alpine
15
16# DNS returns both IPs for 'webserver'
17docker run --rm --network myapp-network alpine nslookup webserverPublishing ports exposes container services to the host and external networks:
Port Publishing Syntax:
1# Publish container port 80 to host port 8080
2docker run -d -p 8080:80 nginx
3
4# Publish to specific interface
5docker run -d -p 127.0.0.1:8080:80 nginx
6
7# Publish to random host port
8docker run -d -P nginx
9
10# Publish UDP port
11docker run -d -p 53:53/udp dns-server
12
13# Multiple ports
14docker run -d \
15 -p 80:80 \
16 -p 443:443 \
17 -p 8080:8080 \
18 nginx
19
20# Port range
21docker run -d -p 8000-8010:8000-8010 myappViewing Port Mappings:
1# View port mappings
2docker port container-name
3# 80/tcp -> 0.0.0.0:8080
4
5# In container listing
6docker ps --format "table {{.Names}}\t{{.Ports}}"Host Networking:
1# Use host network (no NAT)
2docker run -d \
3 --network host \
4 nginx
5
6# Container uses host's network stack directly
7# Ports are exposed without -p flag
8# Best performance, no isolationExpose vs Publish:
1# Dockerfile: EXPOSE documents the port
2EXPOSE 3000
3
4# Does NOT publish the port
5# Use -p or -P at runtime to publish
6
7# -P publishes all EXPOSE'd ports to random host ports
8docker run -d -P myappiptables Rules:
1# Docker manages iptables rules for NAT
2sudo iptables -t nat -L -n
3
4# View Docker's chains
5sudo iptables -L DOCKER -nPatterns for containers to communicate in microservices architectures:
Linked Containers (Legacy):
1# Legacy --link (deprecated, use networks instead)
2docker run -d --name db postgres
3docker run -d --name app --link db:database myapp
4
5# Modern equivalent using networks
6docker network create app-network
7docker run -d --name db --network app-network postgres
8docker run -d --name app --network app-network myapp
9# 'app' can connect to 'db' by nameService Communication Pattern:
1# Create network
2docker network create microservices
3
4# Database service
5docker run -d \
6 --name db \
7 --network microservices \
8 -e POSTGRES_PASSWORD=secret \
9 postgres:15-alpine
10
11# API service connecting to database
12docker run -d \
13 --name api \
14 --network microservices \
15 -e DATABASE_URL=postgres://postgres:secret@db:5432/postgres \
16 -p 3000:3000 \
17 myapi
18
19# Frontend connecting to API
20docker run -d \
21 --name frontend \
22 --network microservices \
23 -e API_URL=http://api:3000 \
24 -p 80:80 \
25 myfrontendMultiple Networks for Isolation:
1# Create separate networks
2docker network create frontend-net
3docker network create backend-net
4
5# Database (backend only)
6docker run -d \
7 --name db \
8 --network backend-net \
9 postgres:15-alpine
10
11# API (both networks)
12docker run -d \
13 --name api \
14 --network backend-net \
15 myapi
16docker network connect frontend-net api
17
18# Frontend (frontend only, can reach API but not DB)
19docker run -d \
20 --name web \
21 --network frontend-net \
22 nginxNetwork Topology:
1┌─────────────────────────────────────────────────────────────┐
2│ Network Isolation │
3├─────────────────────────────────────────────────────────────┤
4│ │
5│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
6│ │ frontend-net │ │ backend-net │ │
7│ │ ┌─────┐ ┌─────┐ │ │ ┌─────┐ ┌─────┐ │ │
8│ │ │ web │────│ api │────┼──┼────│ api │────│ db │ │ │
9│ │ └─────┘ └─────┘ │ │ └─────┘ └─────┘ │ │
10│ │ │ │ │ │
11│ │ web can reach api │ │ api can reach db │ │
12│ │ web CANNOT reach db │ │ db isolated from web │ │
13│ └────────────────────────┘ └──────────────────────────┘ │
14│ │
15└─────────────────────────────────────────────────────────────┘Tools and techniques for debugging Docker network issues:
Network Inspection:
1# Inspect network details
2docker network inspect myapp-network
3
4# Key information:
5# - Subnet and gateway
6# - Connected containers
7# - IP addresses
8# - Network options
9
10# Inspect specific container's network
11docker inspect container-name --format '{{json .NetworkSettings.Networks}}' | jq .Connectivity Testing:
1# Test from inside container
2docker exec container-name ping other-container
3docker exec container-name curl http://api:3000/health
4docker exec container-name nslookup db
5
6# Run debug container on network
7docker run -it --rm \
8 --network myapp-network \
9 nicolaka/netshoot
10
11# Inside netshoot, available tools:
12# ping, curl, dig, nslookup, tcpdump, netstat, ss, ip, tracerouteDNS Debugging:
1# Check DNS resolution
2docker run --rm --network myapp-network alpine nslookup api
3
4# Check embedded DNS server
5docker exec container-name cat /etc/resolv.conf
6# nameserver 127.0.0.11
7
8# Detailed DNS lookup
9docker run --rm --network myapp-network alpine dig apiNetwork Traffic Analysis:
1# Capture traffic on bridge interface
2sudo tcpdump -i docker0 -n
3
4# Capture traffic for specific container
5# Find container's veth interface
6docker exec container-name cat /sys/class/net/eth0/iflink
7# Match with host's veth
8
9# Capture on specific interface
10sudo tcpdump -i veth123abc -nCommon Issues and Solutions:
1# Issue: Container can't resolve other container
2# Solution: Use custom network (not default bridge)
3docker network create mynet
4docker run --network mynet ...
5
6# Issue: Port already in use
7# Solution: Check what's using the port
8sudo lsof -i :8080
9# Or use different port
10docker run -p 8081:80 ...
11
12# Issue: Containers can't reach internet
13# Solution: Check NAT and DNS
14docker run --rm alpine ping 8.8.8.8
15docker run --rm alpine nslookup google.com
16
17# Issue: Cross-host communication fails
18# Solution: Use overlay network in Swarm
19docker network create --driver overlay mynetPerformance Optimization:
1# Use host network for maximum performance
2docker run --network host myapp
3
4# Increase MTU for better throughput
5docker network create \
6 --opt "com.docker.network.driver.mtu"="9000" \
7 high-perf-netBuild a production-like microservices architecture with proper network isolation, service discovery, and external access.
1#!/bin/bash
2# Microservices Network Architecture
3# Complete setup with isolated networks and service discovery
4
5set -e
6
7echo "=============================================="
8echo "Microservices Network Architecture"
9echo "=============================================="
10
11# ==========================================
12# Network Configuration
13# ==========================================
14FRONTEND_NET="frontend-tier"
15BACKEND_NET="backend-tier"
16DATABASE_NET="database-tier"
17
18# ==========================================
19# Step 1: Create Network Infrastructure
20# ==========================================
21setup_networks() {
22 echo "\n=== Creating Networks ==="
23
24 # Frontend network (public-facing services)
25 docker network create \
26 --driver bridge \
27 --subnet 172.30.0.0/24 \
28 --gateway 172.30.0.1 \
29 --label tier=frontend \
30 $FRONTEND_NET
31
32 # Backend network (internal services)
33 docker network create \
34 --driver bridge \
35 --subnet 172.31.0.0/24 \
36 --gateway 172.31.0.1 \
37 --label tier=backend \
38 $BACKEND_NET
39
40 # Database network (data layer)
41 docker network create \
42 --driver bridge \
43 --subnet 172.32.0.0/24 \
44 --gateway 172.32.0.1 \
45 --internal \
46 --label tier=database \
47 $DATABASE_NET
48
49 echo "Networks created:"
50 docker network ls --filter "label=tier"
51}
52
53# ==========================================
54# Step 2: Deploy Database Tier
55# ==========================================
56deploy_database() {
57 echo "\n=== Deploying Database Tier ==="
58
59 # PostgreSQL database
60 docker run -d \
61 --name postgres \
62 --network $DATABASE_NET \
63 --ip 172.32.0.10 \
64 -e POSTGRES_USER=app \
65 -e POSTGRES_PASSWORD=secret123 \
66 -e POSTGRES_DB=microservices \
67 -v postgres-data:/var/lib/postgresql/data \
68 --health-cmd="pg_isready -U app" \
69 --health-interval=10s \
70 postgres:15-alpine
71
72 # Redis cache
73 docker run -d \
74 --name redis \
75 --network $DATABASE_NET \
76 --ip 172.32.0.20 \
77 -v redis-data:/data \
78 --health-cmd="redis-cli ping" \
79 --health-interval=10s \
80 redis:7-alpine
81
82 echo "Database tier deployed"
83}
84
85# ==========================================
86# Step 3: Deploy Backend Services
87# ==========================================
88deploy_backend() {
89 echo "\n=== Deploying Backend Services ==="
90
91 # Create backend API (connected to both backend and database networks)
92 cat > /tmp/api-server.js << 'EOF'
93const http = require('http');
94const PORT = process.env.PORT || 3000;
95
96const server = http.createServer((req, res) => {
97 res.writeHead(200, { 'Content-Type': 'application/json' });
98
99 if (req.url === '/health') {
100 res.end(JSON.stringify({ status: 'healthy', service: 'api' }));
101 } else if (req.url === '/api/data') {
102 res.end(JSON.stringify({
103 message: 'Data from API',
104 db: process.env.DATABASE_URL ? 'connected' : 'not configured',
105 cache: process.env.REDIS_URL ? 'connected' : 'not configured'
106 }));
107 } else {
108 res.end(JSON.stringify({ service: 'api', version: '1.0.0' }));
109 }
110});
111
112server.listen(PORT, () => console.log(\`API running on port \${PORT}\`));
113EOF
114
115 # API Service
116 docker run -d \
117 --name api-service \
118 --network $BACKEND_NET \
119 -e DATABASE_URL=postgres://app:secret123@postgres:5432/microservices \
120 -e REDIS_URL=redis://redis:6379 \
121 -v /tmp/api-server.js:/app/server.js:ro \
122 -w /app \
123 --health-cmd="wget -q --spider http://localhost:3000/health || exit 1" \
124 --health-interval=10s \
125 node:18-alpine node server.js
126
127 # Connect API to database network
128 docker network connect $DATABASE_NET api-service
129
130 # Auth Service
131 docker run -d \
132 --name auth-service \
133 --network $BACKEND_NET \
134 -e DATABASE_URL=postgres://app:secret123@postgres:5432/microservices \
135 -v /tmp/api-server.js:/app/server.js:ro \
136 -w /app \
137 node:18-alpine node server.js
138
139 docker network connect $DATABASE_NET auth-service
140
141 echo "Backend services deployed"
142}
143
144# ==========================================
145# Step 4: Deploy Frontend/Gateway
146# ==========================================
147deploy_frontend() {
148 echo "\n=== Deploying Frontend/Gateway ==="
149
150 # Create nginx config for reverse proxy
151 mkdir -p /tmp/nginx-config
152 cat > /tmp/nginx-config/nginx.conf << 'EOF'
153events {
154 worker_connections 1024;
155}
156
157http {
158 upstream api {
159 server api-service:3000;
160 }
161
162 upstream auth {
163 server auth-service:3000;
164 }
165
166 server {
167 listen 80;
168 server_name localhost;
169
170 location /health {
171 return 200 '{"status":"healthy","service":"gateway"}';
172 add_header Content-Type application/json;
173 }
174
175 location /api/ {
176 proxy_pass http://api/;
177 proxy_http_version 1.1;
178 proxy_set_header Host $host;
179 proxy_set_header X-Real-IP $remote_addr;
180 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
181 }
182
183 location /auth/ {
184 proxy_pass http://auth/;
185 proxy_http_version 1.1;
186 proxy_set_header Host $host;
187 }
188
189 location / {
190 root /usr/share/nginx/html;
191 index index.html;
192 }
193 }
194}
195EOF
196
197 # Create simple frontend
198 mkdir -p /tmp/nginx-html
199 cat > /tmp/nginx-html/index.html << 'EOF'
200<!DOCTYPE html>
201<html>
202<head>
203 <title>Microservices Demo</title>
204 <style>
205 body { font-family: Arial; max-width: 800px; margin: 50px auto; padding: 20px; }
206 .status { padding: 15px; margin: 10px 0; border-radius: 5px; }
207 .healthy { background: #d4edda; }
208 .error { background: #f8d7da; }
209 pre { background: #f4f4f4; padding: 10px; overflow-x: auto; }
210 </style>
211</head>
212<body>
213 <h1>Microservices Architecture Demo</h1>
214 <div id="results"></div>
215 <script>
216 async function checkServices() {
217 const services = ['health', 'api/data', 'auth'];
218 const results = document.getElementById('results');
219 results.innerHTML = '';
220
221 for (const svc of services) {
222 try {
223 const res = await fetch('/' + svc);
224 const data = await res.json();
225 results.innerHTML += '<div class="status healthy">'
226 + '<strong>/' + svc + '</strong>'
227 + '<pre>' + JSON.stringify(data, null, 2) + '</pre></div>';
228 } catch (e) {
229 results.innerHTML += '<div class="status error">'
230 + '<strong>/' + svc + '</strong>: Error</div>';
231 }
232 }
233 }
234 checkServices();
235 </script>
236</body>
237</html>
238EOF
239
240 # API Gateway (nginx)
241 docker run -d \
242 --name gateway \
243 --network $FRONTEND_NET \
244 -p 80:80 \
245 -v /tmp/nginx-config/nginx.conf:/etc/nginx/nginx.conf:ro \
246 -v /tmp/nginx-html:/usr/share/nginx/html:ro \
247 --health-cmd="curl -f http://localhost/health || exit 1" \
248 --health-interval=10s \
249 nginx:alpine
250
251 # Connect gateway to backend network
252 docker network connect $BACKEND_NET gateway
253
254 echo "Frontend/Gateway deployed"
255}
256
257# ==========================================
258# Step 5: Verify Architecture
259# ==========================================
260verify_architecture() {
261 echo "\n=== Verifying Architecture ==="
262
263 echo "\nNetworks:"
264 docker network ls --filter "label=tier" --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}"
265
266 echo "\nContainers:"
267 docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
268
269 echo "\nNetwork Connectivity:"
270 echo " Frontend tier:"
271 docker network inspect $FRONTEND_NET --format '{{range .Containers}} - {{.Name}} ({{.IPv4Address}}){{println}}{{end}}'
272
273 echo " Backend tier:"
274 docker network inspect $BACKEND_NET --format '{{range .Containers}} - {{.Name}} ({{.IPv4Address}}){{println}}{{end}}'
275
276 echo " Database tier:"
277 docker network inspect $DATABASE_NET --format '{{range .Containers}} - {{.Name}} ({{.IPv4Address}}){{println}}{{end}}'
278
279 echo "\nService Health:"
280 for container in gateway api-service auth-service postgres redis; do
281 health=$(docker inspect $container --format '{{.State.Health.Status}}' 2>/dev/null || echo "no healthcheck")
282 echo " $container: $health"
283 done
284}
285
286# ==========================================
287# Step 6: Test Connectivity
288# ==========================================
289test_connectivity() {
290 echo "\n=== Testing Connectivity ==="
291
292 sleep 5 # Wait for services
293
294 echo "\nGateway -> API:"
295 docker exec gateway wget -q -O - http://api-service:3000/api/data || echo "Failed"
296
297 echo "\nAPI -> Database:"
298 docker exec api-service ping -c 1 postgres || echo "Ping failed"
299
300 echo "\nGateway -> Database (should fail - isolated):"
301 docker exec gateway ping -c 1 -W 1 postgres 2>/dev/null && echo "WARNING: Gateway can reach database!" || echo "OK - Database is isolated"
302
303 echo "\nExternal access:"
304 curl -s http://localhost/health | jq . || echo "Gateway not responding"
305 curl -s http://localhost/api/data | jq . || echo "API not responding"
306}
307
308# ==========================================
309# Cleanup
310# ==========================================
311cleanup() {
312 echo "\n=== Cleanup ==="
313 docker rm -f gateway api-service auth-service postgres redis 2>/dev/null || true
314 docker network rm $FRONTEND_NET $BACKEND_NET $DATABASE_NET 2>/dev/null || true
315 docker volume rm postgres-data redis-data 2>/dev/null || true
316 rm -rf /tmp/nginx-config /tmp/nginx-html /tmp/api-server.js
317 echo "Cleanup complete!"
318}
319
320# ==========================================
321# Main
322# ==========================================
323main() {
324 setup_networks
325 deploy_database
326 sleep 5
327 deploy_backend
328 deploy_frontend
329 verify_architecture
330 test_connectivity
331
332 echo "\n=============================================="
333 echo "Architecture Deployed Successfully!"
334 echo "=============================================="
335 echo "
336Access Points:
337 Web UI: http://localhost/
338 API: http://localhost/api/data
339 Auth: http://localhost/auth/
340
341Network Architecture:
342 Frontend Tier: gateway
343 Backend Tier: api-service, auth-service, gateway
344 Database Tier: postgres, redis, api-service, auth-service
345
346Note: Database tier is isolated (--internal flag)
347 Gateway cannot directly access databases
348
349Commands:
350 cleanup - Remove all containers and networks
351"
352}
353
354mainYour progress is saved in this browser, on this device only.