Docker networking determines how containers communicate with each other and the outside world. Understanding the different network drivers and when to use each is essential for building secure, performant containerized applications. This guide covers bridge, host, overlay, and macvlan networks with practical examples.
Network Types
- bridge — default; containers on same bridge can communicate; isolated from host network
- host — container shares the host network stack; best performance, no isolation
- overlay — multi-host networking for Docker Swarm and distributed applications
- macvlan — assigns a MAC address to container; appears as physical device on network
- none — no networking; completely isolated
Custom Bridge Networks
# Create a custom bridge network
docker network create --driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
--opt com.docker.network.bridge.name=br-myapp \
myapp-network
# Run containers on the network
docker run -d --name web --network myapp-network nginx
docker run -d --name api --network myapp-network node-api
docker run -d --name db --network myapp-network postgres
# Containers can reach each other by name (built-in DNS)
docker exec web ping api # Works!
docker exec api ping db # Works!
Docker Compose Networks
services:
web:
image: nginx
networks:
- frontend
api:
image: node:20
networks:
- frontend
- backend
db:
image: postgres:16
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access — DB only reachable from API
Network Isolation Patterns
# Pattern: DMZ with internal network
# Frontend (public) → API (bridge between networks) → Database (internal only)
networks:
public:
driver: bridge
internal:
driver: bridge
internal: true # Cannot reach the internet
services:
nginx:
networks: [public]
ports: ["80:80"]
api:
networks: [public, internal] # Bridge between networks
postgres:
networks: [internal] # Only accessible from internal network
Host Network
# Container shares host network — no port mapping needed
docker run -d --network host nginx
# Nginx listens directly on host port 80
# Use cases:
# - Maximum network performance (no NAT overhead)
# - Applications that need to see real client IPs
# - Services that bind to many dynamic ports
Macvlan Network
# Container gets its own IP on the 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 \
--name container1 nginx
# Container is accessible at 192.168.1.100 from the LAN
# Useful for: legacy apps needing specific IPs, network appliances
DNS Configuration
# Custom DNS for a network
docker network create --driver bridge \
--opt com.docker.network.bridge.enable_ip_masquerade=true \
--dns 10.0.0.1 \
--dns 1.1.1.1 \
my-network
# Per-container DNS
docker run --dns 10.0.0.1 --dns-search example.com nginx
# Aliases for service discovery
services:
postgres:
networks:
backend:
aliases:
- db
- database
- pg
Inspecting Networks
# List networks
docker network ls
# Inspect a network (show connected containers)
docker network inspect myapp-network
# Find which network a container is on
docker inspect --format='{{json .NetworkSettings.Networks}}' container_name | jq
# Connect/disconnect containers from networks
docker network connect myapp-network existing-container
docker network disconnect myapp-network existing-container
Best Practices
- Always create custom bridge networks instead of using the default bridge — custom bridges provide DNS resolution by container name
- Use
internal: truenetworks for databases and services that should not reach the internet - Separate frontend and backend services into different networks with the API bridging them
- Use host networking only when performance is critical and network isolation is not needed
- Assign static IPs only when necessary — rely on Docker DNS for service discovery
- Clean up unused networks periodically:
docker network prune