Docker Networking

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=overlay

Common 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 IPAddress

Host 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:80

Macvlan 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:alpine

Multi-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-app

Network 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: bridge

Port 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-app

Overlay 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 5432

Network 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-container

Health 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: true

Performance 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-app

Load 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: true

Security 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 web

Network 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: true

Monitoring 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 1

This 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.

Last updated on