env.dev

Docker Networking: Bridge, Host, Overlay & Compose

Understand Docker networking: bridge, host, overlay networks, port mapping, DNS resolution, and Docker Compose networking.

Last updated:

Docker networking controls how containers communicate with each other, the host, and external networks. Docker provides several network drivers — bridge, host, overlay, and none — each suited to different deployment scenarios. Understanding these drivers is essential for building multi-container applications, securing inter-service traffic, and debugging connectivity issues.

What Are the Docker Network Drivers?

Docker uses pluggable network drivers. The default is bridge, which creates an isolated virtual network on the host. Each driver has different isolation, performance, and discoverability characteristics.

DriverScopeDNSUse Case
bridgeSingle hostUser-defined onlyDefault — isolated containers on one host
hostSingle hostHost's DNSNo network isolation — max performance
overlayMulti-hostYesSwarm services across multiple nodes
noneN/ANoCompletely isolated — no networking
macvlanSingle hostNoAssign a MAC address — appear as physical device

How Does Bridge Networking Work?

The default bridge network (docker0) provides basic connectivity but no automatic DNS resolution between containers. Always create a user-defined bridge network instead — it provides DNS, better isolation, and the ability to connect/disconnect containers at runtime.

Bridge network basics
# Create a user-defined bridge network
docker network create app-network

# Run containers on the network
docker run -d --name api --network app-network node:22-slim
docker run -d --name db --network app-network postgres:17

# The 'api' container can now reach 'db' by name
# From inside 'api': ping db → resolves to the container's IP

# Inspect the network (see connected containers, subnet, gateway)
docker network inspect app-network

# Disconnect a container from the network
docker network disconnect app-network api

# Remove the network (must disconnect all containers first)
docker network rm app-network

Default vs user-defined bridge: The default docker0 bridge requires --link for container name resolution (deprecated). User-defined bridges have automatic DNS, configurable subnets, and better isolation between groups of containers.

How Does Port Mapping Work?

Port mapping publishes container ports to the host using -p. Without it, container ports are only accessible from within the Docker network.

Port mapping options
# Map host port 8080 → container port 3000
docker run -p 8080:3000 myapp

# Map to a specific host interface (localhost only)
docker run -p 127.0.0.1:8080:3000 myapp

# Map a range of ports
docker run -p 8000-8010:8000-8010 myapp

# Let Docker pick a random host port
docker run -p 3000 myapp
# Check assigned port: docker port <container_id>

# UDP port mapping
docker run -p 5353:53/udp dns-server

# Multiple port mappings
docker run -p 80:80 -p 443:443 nginx

How Does DNS Resolution Work in Docker?

On user-defined networks, Docker runs an embedded DNS server at 127.0.0.11. Containers can resolve each other by container name or network alias. This is the foundation of service discovery in Docker.

DNS and service discovery
# Container name = DNS name (on user-defined networks)
docker run -d --name redis --network app-network redis:7

# From another container on the same network:
# redis:6379 resolves to the container's IP

# Network aliases — multiple DNS names for one container
docker run -d --name redis-primary \
  --network app-network \
  --network-alias redis \
  --network-alias cache \
  redis:7

# Both 'redis' and 'cache' resolve to this container

# Debug DNS resolution
docker run --rm --network app-network alpine nslookup redis

How Does Docker Compose Networking Work?

Docker Compose automatically creates a network for each project. All services in a compose.yaml can reach each other by service name. You can also define custom networks to isolate groups of services.

compose.yaml with multiple networks
services:
  api:
    image: node:22-slim
    ports:
      - "3000:3000"
    networks:
      - frontend
      - backend
    depends_on:
      - db
      - redis

  web:
    image: nginx:latest
    ports:
      - "80:80"
    networks:
      - frontend
    # 'web' can reach 'api' but NOT 'db' or 'redis'

  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: secret
    networks:
      - backend
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # No external access — db/redis isolated

volumes:
  pgdata:

How Does Multi-Host Networking Work?

Overlay networks span multiple Docker hosts, enabling containers on different machines to communicate as if on the same LAN. This is used in Docker Swarm and can be attached to standalone containers with the --attachable flag.

Overlay network for multi-host communication
# Initialize Swarm (required for overlay networks)
docker swarm init

# Create an attachable overlay network
docker network create -d overlay --attachable multi-host-net

# Deploy a service across multiple nodes
docker service create \
  --name api \
  --network multi-host-net \
  --replicas 3 \
  myapp:latest

# Standalone containers can also join (with --attachable)
docker run -d --name debug --network multi-host-net alpine sleep 3600

# Inspect overlay network
docker network inspect multi-host-net

How Do You Debug Docker Networking Issues?

When containers cannot reach each other, use these commands to diagnose the issue.

Debugging commands
# List all networks
docker network ls

# Inspect a network (shows connected containers, IPs, subnet)
docker network inspect app-network

# Check which networks a container is connected to
docker inspect --format='{{json .NetworkSettings.Networks}}' my-container

# Test connectivity from inside a container
docker exec -it api ping db
docker exec -it api curl http://api:3000/health

# Run a temporary debug container on the network
docker run --rm -it --network app-network nicolaka/netshoot
# Inside: dig redis, nslookup db, curl api:3000, tcpdump, etc.

# Check published ports
docker port my-container

# View iptables rules Docker created (Linux)
sudo iptables -t nat -L -n | grep DOCKER

Key Takeaways

  • • Always use user-defined bridge networks — they provide automatic DNS resolution between containers
  • • The default docker0 bridge lacks DNS and should be avoided
  • • Port mapping (-p host:container) is required to expose container ports to the host
  • • Docker Compose creates a project network automatically — services resolve by service name
  • • Use internal: true networks to isolate backend services from external access
  • • Overlay networks enable cross-host communication in Swarm deployments
  • • Use docker network inspect and netshoot for debugging connectivity

Frequently Asked Questions

What is the default Docker network?

Docker creates a default bridge network. Containers on this network can communicate by IP but not by name. User-defined bridge networks add automatic DNS resolution between containers by container name.

When should I use host networking?

Use host networking (--network host) when you need maximum network performance or need to bind to many ports. The container shares the host network stack directly. Not available on Docker Desktop for Mac/Windows.

How does Docker Compose networking work?

Compose automatically creates a network for each project. Services can reach each other by service name. Use networks: in compose.yml to create multiple isolated networks or connect to external networks.

Was this helpful?

Stay up to date

Get notified about new guides, tools, and cheatsheets.