Skip to content

Docker_networking_advanced

Chapter 14: Docker Networking Advanced - Custom Networks, DNS, and Load Balancing

Section titled “Chapter 14: Docker Networking Advanced - Custom Networks, DNS, and Load Balancing”
  1. Docker Networking Overview
  2. Network Drivers
  3. Custom Bridge Networks
  4. Overlay Networks
  5. DNS and Service Discovery
  6. Load Balancing
  7. Network Isolation
  8. Macvlan Networks
  9. Network Plugins
  10. Hands-on Lab
  11. Summary

┌─────────────────────────────────────────────────────────────────────────────┐
│ DOCKER NETWORKING ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Docker Network Namespace │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Container │ │ Container │ │ Container │ │ │
│ │ │ A │ │ B │ │ C │ │ │
│ │ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │ │
│ │ │ │ eth0 │◄──┼────┼─│ eth0 │◄──┼────┼─│ eth0 │ │ │ │
│ │ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Docker Bridge (docker0) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ veth pairs │ │ │
│ │ │ vethA ── eth0 vethB ── eth0 vethC ── eth0 │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────────────────┴───────────────────────────────┐ │ │
│ │ │ iptables / NAT / Routing │ │ │
│ │ └───────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Host Network (eth0) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Terminal window
# List all networks
docker network ls
# Output:
# NETWORK ID NAME DRIVER SCOPE
# abc123... bridge bridge local
# def456... host host local
# ghi789... none null local
# Inspect default bridge
docker network inspect bridge

┌─────────────────────────────────────────────────────────────────────────────┐
│ DOCKER NETWORK DRIVERS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Driver │ Scope │ Use Case │ Isolation │
│ ────────────┼─────────┼─────────────────────────────────┼──────────── │
│ bridge │ local │ Single host, default │ High │
│ host │ local │ Remove network isolation │ None │
│ overlay │ swarm │ Multi-host, Docker Swarm │ High │
│ macvlan │ local │ Direct network access │ Highest │
│ none │ local │ Disable networking │ Complete │
│ plugins │ varies │ Third-party solutions │ Varies │
│ │
│ Detailed Comparison: │
│ ─────────────────── │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ BRIDGE │ │ OVERLAY │ │ MACVLAN │ │
│ │ │ │ │ │ │ │
│ │ Virtual eth │ │ VXLAN tunnel │ │ Direct MAC │ │
│ │ on host │ │ Multi-host │ │ Per container │ │
│ │ NAT for ext │ │ Encrypted │ │ No NAT │ │
│ │ │ │ Service disc │ │ Legacy apps │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Terminal window
# Create a custom bridge network
docker network create \
--driver bridge \
--subnet=172.20.0.0/16 \
--ip-range=172.20.5.0/24 \
--gateway=172.20.0.1 \
my-bridge-network
# List networks
docker network ls
# Inspect network
docker network inspect my-bridge-network
Terminal window
# Run containers on custom network
docker run -d --name web --network my-bridge-network nginx
docker run -d --name api --network my-bridge-network myapi:latest
docker run -d --name db --network my-bridge-network postgres:15
# Connect existing container to network
docker network connect my-bridge-network existing-container
# Disconnect from network
docker network disconnect my-bridge-network existing-container
┌─────────────────────────────────────────────────────────────────────────────┐
│ NETWORK ISOLATION WITH BRIDGES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Default Bridge (docker0) Custom Bridge │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ │ │ │ │
│ │ ┌─────┐ ┌─────┐ │ │ ┌─────┐ ┌─────┐ │ │
│ │ │ web │ │ api │ │ │ │ web │ │ api │ │ │
│ │ └──┬──┘ └──┬──┘ │ │ └──┬──┘ └──┬──┘ │ │
│ │ │ │ │ │ │ │ │ │
│ │ └──────┴──────│ │ └──────┴──────│ │
│ │ │ │ │ │ │ │
│ │ ▼ │ │ ▼ │ │
│ │ ┌─────────┐ │ │ ┌─────────┐ │ │
│ │ │ DNS │ │ │ │ DNS │ │ │
│ │ │(default)│ │ │ │(custom) │ │ │
│ │ └─────────┘ │ │ └─────────┘ │ │
│ │ │ │ │ │
│ │ ✓ Can reach │ │ ✓ Can reach │ │
│ │ each other │ │ each other │ │
│ │ ✗ No isolation │ │ ✓ Can isolate │ │
│ │ │ │ ✓ Custom DNS │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ Problem: Solution: │
│ Containers can access each other Use separate networks │
│ by default on default bridge for isolation │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│ OVERLAY NETWORK ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ External Network│ │
│ └────────┬────────┘ │
│ │ │
│ ┌───────────────────┼───────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Host A │ │ Host B │ │ Host C │ │
│ │ │ │ │ │ │ │
│ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │
│ │ │ Container │ │ │ │ Container │ │ │ │ Container │ │ │
│ │ │ App1 │ │ │ │ App2 │ │ │ │ App3 │ │ │
│ │ └──────┬──────┘ │ │ └──────┬──────┘ │ │ └──────┬──────┘ │ │
│ │ │ │ │ │ │ │ │ │ │
│ │ │ VXLAN │ │ │ VXLAN │ │ │ VXLAN │ │
│ │ │ Tunnel │ │ │ Tunnel │ │ │ Tunnel │ │
│ │ └────────┘ │ └────────┘ │ └────────┘ │
│ └─────────┬───────────┘ └─────────┬───────────┘ └─────────┬─────────┘ │
│ │ │ │ │
│ └───────────────────────────┼───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ OVERLAY NETWORK (vxlan) │ │
│ │ │ │
│ │ • Encapsulates container traffic in UDP packets │ │
│ │ • Works across multiple hosts │ │
│ │ • Automatic service discovery │ │
│ │ • Built-in load balancing │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Terminal window
# Initialize Docker Swarm first (required for overlay networks)
docker swarm init
# Create overlay network
docker network create \
--driver overlay \
--attachable \
my-overlay-network
# Run containers on overlay network
docker run -d --name web --network my-overlay-network nginx
docker run -d --name api --network my-overlay-network myapi:latest
Terminal window
# Create encrypted overlay network
docker network create \
--driver overlay \
--opt encrypted \
--attachable \
secure-overlay

┌─────────────────────────────────────────────────────────────────────────────┐
│ DOCKER DNS SERVICE DISCOVERY │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Docker DNS Resolution Flow │
│ ──────────────────────────── │
│ │
│ ┌─────────────────┐ │
│ │ Container A │ │
│ │ │ │
│ │ ┌───────────┐ │ 1. Query: "api" │
│ │ │ app │─┼────────────────────────────────┐ │
│ │ └───────────┘ │ │ │
│ │ │ │ ▼ │
│ │ ┌─────┴─────┐ │ ┌─────────────────────────┐ │
│ │ │ DNS │ │ │ Docker DNS Server │ │
│ │ │ Resolver │ │ │ (127.0.0.11) │ │
│ │ └───────────┘ │ │ │ │
│ └────────┬────────┘ │ • Container names │ │
│ │ │ • Network aliases │ │
│ │ │ • Domain search │ │
│ │ │ │ │
│ │ 2. Response: 172.18.0.2 └────────────┬────────────┘ │
│ │◄───────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Container B │ │
│ │ (Name: api) │ │
│ │ IP: 172.18.0.2│ │
│ └─────────────────┘ │
│ │
│ DNS Records: │
│ ─────────── │
│ • Container name → IP address │
│ • Network alias → IP address │
│ • Network-scoped (only accessible within network) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Terminal window
# Create network with custom DNS
docker network create \
--driver bridge \
--dns=8.8.8.8 \
--gateway=172.25.0.1 \
--subnet=172.25.0.0/16 \
custom-dns-network
# Run containers
docker run -d --name web --network custom-dns-network nginx
docker run -d --name api --network custom-dns-network myapi
# From web container, access api by name
docker exec web curl http://api:8080
# Add network alias
docker network connect --alias api-service my-network my-container
# Inspect DNS config
docker exec web cat /etc/resolv.conf
Terminal window
# Run with custom DNS servers
docker run --dns 8.8.8.8 --dns 8.8.4.4 nginx
# Run with custom search domain
docker run --dns-search mycompany.local nginx
# Run with specific hostname
docker run --hostname myapp-server nginx

┌─────────────────────────────────────────────────────────────────────────────┐
│ DOCKER INTERNAL LOAD BALANCING │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ Service Name │ │
│ │ (myapp) │ │
│ └────────┬────────┘ │
│ │ │
│ │ Virtual IP (VIP) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Load Balancer (HAProxy/Docker) │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Round │ │ Least │ │ Source │ │ Random │ │ │
│ │ │ Robin │ │ Conn │ │ Hash │ │ │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────┼──────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Container 1 │ │ Container 2 │ │ Container 3 │ │
│ │ 172.18.0.2 │ │ 172.18.0.3 │ │ 172.18.0.4 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ Features: │
│ • Automatic distribution │
│ • Health checks │
│ • Service discovery integration │
│ • No external LB needed │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Terminal window
# Run multiple replicas (Swarm)
docker service create \
--name myapp \
--replicas 3 \
--publish published=8080,target=80 \
nginx
# All three containers accessible via port 8080
# Docker distributes traffic across replicas
# haproxy/Dockerfile
FROM haproxy:2.8
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
# haproxy.cfg
global
log stdout format raw local0
maxconn 4096
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http_front
bind *:80
default_backend api_back
backend api_back
balance roundrobin
server api1 api1:8080 check
server api2 api2:8080 check
server api3 api3:8080 check

Terminal window
# Create internal network (no external access)
docker network create --driver bridge --internal backend-network
# Containers can only communicate with each other
# Cannot access external networks or internet
docker run -d --name db --network backend-network postgres:15
docker run -d --name app --network backend-network myapp
# App can reach db, but neither can reach internet
┌─────────────────────────────────────────────────────────────────────────────┐
│ NETWORK SEGMENTATION STRATEGY │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Production Network │ │
│ │ │ │
│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │
│ │ │ Frontend │ │ Backend │ │ Database │ │ │
│ │ │ Network │ │ Network │ │ Network │ │ │
│ │ │ │ │ │ │ Internal │ │ │
│ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │ │ │
│ │ │ │ web-1 │ │ │ │ api-1 │ │ │ ┌─────────┐ │ │ │
│ │ │ │ web-2 │ │ │ │ api-2 │ │ │ │ postgres│ │ │ │
│ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ │
│ │ └───────┬───────┘ └───────┬───────┘ └─────┬─────┘ │ │
│ │ │ │ │ │ │
│ └───────────┼────────────────────┼───────────────────┼─────────┘ │
│ │ │ │ │
│ │ ┌──────────┼───────────────────┘ │
│ │ │ │ │
│ │ ▼ ▼ │
│ │ ┌─────────────────────────────────────┐ │
│ │ │ Public Network │ │
│ │ │ (Load Balancer / Ingress) │ │
│ │ └─────────────────────────────────────┘ │
│ │ │
│ │ Traffic Flow: │
│ │ ──────────── │
│ │ Internet → LB → Frontend → Backend → DB │
│ │ │
│ │ Isolation Rules: │
│ │ ──────────────── │
│ │ • Frontend → Backend: ALLOW │
│ │ • Frontend → Database: DENY │
│ │ • Backend → Database: ALLOW │
│ │ • Any → Internal: DENY │
│ │ │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│ MACVLAN NETWORKING │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Traditional Bridge Mode Macvlan Mode │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ Host │ │ Host │ │
│ │ │ │ │ │
│ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ │ Container │ │ │ │ Container │ │ │
│ │ │ ┌────────┐ │ │ │ │ ┌────────┐ │ │ │
│ │ │ │ eth0 │ │ │ │ │ │ eth0 │ │ │ │
│ │ │ └───┬────┘ │ │ │ │ └──┬────┘ │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │ ┌─┴──────┐ │ │ │ │ ┌──┴──────┐ │ │ │
│ │ │ │ bridge │ │ │ │ │ │ macvlan │ │ │ │
│ │ │ └───┬────┘ │ │ │ │ └──┬──────┘ │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ └──────┴──────┘ │ │ └─────┴────────┘ │ │
│ │ │ │ │ │ │ │
│ │ ┌───────┴───────────┘ │ ┌───────┴───────────┘ │
│ │ │ eth0 (Host) │ │ │ eth0 (Host) │ │
│ │ └─────────────────┘ │ └─────────────────┘ │
│ │ │ │
│ │ NAT translation needed │ Direct access to network │
│ │ Container has virtual IP │ Container gets real IP │
│ │ │ Better performance │
│ └─────────────────────────────────┴─────────────────────────────────┘ │
│ │
│ Use Cases: │
│ • Legacy applications that need direct network access │
│ • Applications requiring specific IP addresses │
│ • High-performance workloads │
│ • migrating from VMs to containers │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Terminal window
# Create macvlan network
docker network create -d macvlan \
--subnet=192.168.100.0/24 \
--gateway=192.168.100.1 \
-o parent=eth0 \
my-macvlan
# Run container with macvlan
docker run -d --name myapp \
--network my-macvlan \
--ip 192.168.100.10 \
myimage:latest

┌─────────────────────────────────────────────────────────────────────────────┐
│ DOCKER NETWORK PLUGINS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Popular Network Plugins │
│ ───────────────────── │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ Calico │ │ Weave │ │ Flannel │ │
│ │ │ │ │ │ │ │
│ │ • BGP │ │ • Mesh │ │ • VXLAN │ │
│ │ • Policy │ │ • Encryption │ │ • Simple │ │
│ │ • Scalable │ │ • Easy │ │ • K8s native │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ Canal │ │ Romana │ │ Cilium │ │
│ │ │ │ │ │ │ │
│ │ • Calico+ │ │ • Policy │ │ • eBPF │ │
│ │ Flannel │ │ • CNI │ │ • Observab. │ │
│ │ │ │ │ │ • Hubble │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
│ │
│ Installing Plugins: │
│ ────────────────── │
│ docker plugin install <plugin> │
│ │
│ Example: │
│ docker plugin install weaveworks/plugin:net │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

In this hands-on lab, we’ll create a secure multi-tier network architecture.

  • Docker installed
  • Docker Swarm initialized (optional, for overlay networks)
Terminal window
# Step 1: Create networks
# Frontend network (public-facing)
docker network create --driver bridge frontend-network
# Backend network (internal)
docker network create --driver bridge --internal backend-network
# Database network (most restricted)
docker network create --driver bridge --internal database-network
# Step 2: List networks
docker network ls
# Step 3: Start services in appropriate networks
# Database layer
docker run -d \
--name database \
--network database-network \
-e POSTGRES_PASSWORD=secret \
postgres:15
# Backend API
docker run -d \
--name api \
--network backend-network \
myapi:latest
# Connect API to database network
docker network connect database-network api
# Frontend web server
docker run -d \
--name frontend \
--network frontend-network \
-p 8080:80 \
nginx
# Connect frontend to backend
docker network connect backend-network frontend
# Step 4: Verify network isolation
# From frontend, verify connectivity
docker exec frontend ping api # Should work
docker exec frontend ping database # Should NOT work
# From api, verify connectivity
docker exec api ping database # Should work
# Step 5: Test web access
curl http://localhost:8080
# Step 6: Clean up
docker stop frontend api database
docker rm frontend api database
docker network rm frontend-network backend-network database-network

  1. Network Drivers - Choose the right driver for your use case
  2. Custom Networks - Create custom networks for better control
  3. DNS - Docker provides built-in DNS for service discovery
  4. Isolation - Use internal networks for security
  5. Overlay Networks - For multi-host communication
  6. Macvlan - For legacy apps needing direct network access
Terminal window
# Create networks
docker network create --driver bridge my-network
docker network create --driver overlay --attachable my-overlay
# Inspect network
docker network inspect <network>
# Connect/disconnect containers
docker network connect <network> <container>
docker network disconnect <network> <container>
# DNS lookup
docker exec <container> nslookup <service-name>

In the next chapter, we’ll explore Docker in CI/CD (Chapter 15), covering:

  • Building Docker images in CI/CD pipelines
  • Testing containers
  • Registry integration
  • Deployment strategies