Containers couldn’t talk to each other. Some worked, some didn’t. Network debugging took hours. I didn’t understand Docker networking properly.

I spent a week learning Docker networking inside out. Now I know exactly which network mode to use and how to debug issues in minutes.

Table of Contents

Network Modes

Docker supports 5 network modes:

  1. Bridge (default): Isolated network
  2. Host: Use host’s network
  3. None: No networking
  4. Overlay: Multi-host networking
  5. Macvlan: Assign MAC address

Bridge Network

Default mode. Containers get private IP:

docker run -d --name web nginx
docker inspect web | grep IPAddress
# "IPAddress": "172.17.0.2"

Containers on same bridge can communicate:

docker run -d --name app1 nginx
docker run -d --name app2 nginx

# app2 can reach app1
docker exec app2 ping app1

Custom Bridge Network

Better than default:

docker network create my-network

docker run -d --name web --network my-network nginx
docker run -d --name app --network my-network alpine sleep 1000

# DNS resolution works!
docker exec app ping web

Benefits:

  • Automatic DNS resolution
  • Better isolation
  • Can connect/disconnect on the fly

Host Network

Container uses host’s network stack:

docker run -d --network host nginx

No port mapping needed. Container binds directly to host ports.

Use cases:

  • Maximum performance
  • Need to bind to host IP
  • Network monitoring tools

Drawbacks:

  • No isolation
  • Port conflicts
  • Less portable

None Network

No networking:

docker run -d --network none alpine sleep 1000

Use cases:

  • Maximum isolation
  • Custom networking setup
  • Security-sensitive workloads

Overlay Network

Multi-host networking (Swarm/Kubernetes):

docker network create -d overlay my-overlay

docker service create --name web --network my-overlay nginx

Containers on different hosts can communicate!

Port Mapping

Expose container ports:

# Map container port 80 to host port 8080
docker run -d -p 8080:80 nginx

# Map to random host port
docker run -d -P nginx

# Bind to specific IP
docker run -d -p 192.168.1.100:8080:80 nginx

Network Inspection

List networks:

docker network ls

Inspect network:

docker network inspect bridge

See container’s network:

docker inspect web | grep -A 20 NetworkSettings

DNS Resolution

Custom bridge networks have built-in DNS:

docker network create app-network

docker run -d --name db --network app-network postgres
docker run -d --name web --network app-network nginx

# web can resolve 'db'
docker exec web ping db

Connecting Multiple Networks

Container can join multiple networks:

docker network create frontend
docker network create backend

docker run -d --name web --network frontend nginx
docker network connect backend web

# web is now on both networks

Network Performance

Benchmark:

# Bridge network
docker run --rm --network bridge networkstatic/iperf3 -c server

# Host network (faster)
docker run --rm --network host networkstatic/iperf3 -c server

Results:

  • Bridge: ~9 Gbps
  • Host: ~10 Gbps (native)

Troubleshooting

1. Container can’t reach internet:

# Check DNS
docker exec container cat /etc/resolv.conf

# Check routing
docker exec container ip route

# Test connectivity
docker exec container ping 8.8.8.8
docker exec container ping google.com

2. Containers can’t communicate:

# Check if on same network
docker network inspect my-network

# Check firewall rules
sudo iptables -L -n

# Check container IPs
docker inspect container1 | grep IPAddress
docker inspect container2 | grep IPAddress

3. Port mapping not working:

# Check if port is actually mapped
docker port container

# Check if service is listening
docker exec container netstat -tlnp

# Check host firewall
sudo iptables -L -n | grep 8080

Docker Compose Networking

Automatic network creation:

version: '3'
services:
  web:
    image: nginx
    ports:
      - "8080:80"
    networks:
      - frontend
  
  app:
    image: myapp
    networks:
      - frontend
      - backend
  
  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
  backend:

Services can resolve each other by name!

Network Drivers

bridge: Single host overlay: Multi-host (Swarm) macvlan: Assign MAC addresses ipvlan: IP-based networking

Macvlan Example

Containers get MAC addresses on physical network:

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  macvlan-net

docker run -d --network macvlan-net --ip=192.168.1.100 nginx

Container appears as physical device on network!

Network Security

1. Isolate networks:

docker network create --internal private-network

No external access!

2. Limit inter-container communication:

docker network create --opt com.docker.network.bridge.enable_icc=false isolated

3. Use network policies (Kubernetes):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Production Setup

Our microservices network:

version: '3'
services:
  nginx:
    image: nginx
    networks:
      - public
      - private
    ports:
      - "80:80"
  
  api:
    image: api
    networks:
      - private
  
  db:
    image: postgres
    networks:
      - private
    environment:
      POSTGRES_PASSWORD: secret

networks:
  public:
    driver: bridge
  private:
    driver: bridge
    internal: true
  • nginx: public + private
  • api: private only
  • db: private only (no external access)

Monitoring

Network metrics:

# Container network stats
docker stats

# Detailed network info
docker exec container cat /proc/net/dev

# Network connections
docker exec container netstat -an

Prometheus metrics:

# Network bytes received
rate(container_network_receive_bytes_total[5m])

# Network bytes transmitted
rate(container_network_transmit_bytes_total[5m])

Common Patterns

1. Frontend-Backend separation:

Internet → nginx (public) → api (private) → db (private)

2. Service mesh:

All services on overlay network with service discovery

3. Sidecar proxy:

App container + Envoy proxy in same pod

Results

Before:

  • Didn’t understand network modes
  • Used default bridge for everything
  • Network debugging took hours

After:

  • Use appropriate network mode
  • Custom networks with DNS
  • Debug network issues in minutes

Lessons Learned

  1. Use custom bridge networks - Better than default
  2. DNS is automatic - On custom networks
  3. Host network for performance - When needed
  4. Isolate sensitive services - Use internal networks
  5. Monitor network metrics - Catch issues early

Conclusion

Docker networking is powerful but requires understanding. Choose the right mode for your use case.

Key takeaways:

  1. Custom bridge for most cases
  2. Host for performance
  3. Overlay for multi-host
  4. Use network isolation
  5. Monitor and troubleshoot

Master Docker networking. Your containers will thank you.