Skip to content
C Codeloom
Docker

Docker Networking: Bridge, Host, and Overlay Networks Explained

A clear guide to Docker's three most common network drivers, when to pick each one, and how packets actually flow between containers in real deployments.

·4 min read · By Codeloom
Intermediate 9 min read

What you'll learn

  • How the default bridge network isolates containers
  • When host networking is the right tradeoff
  • How overlay networks span multiple hosts
  • How to inspect and debug container networking
  • Common networking pitfalls in production

Prerequisites

  • Basic Docker CLI experience and a working Docker installation

What and Why

Docker ships with several built-in network drivers. The three you will touch most often are bridge, host, and overlay. Each one trades isolation, performance, and portability differently. Picking the wrong driver leads to confusing port-binding errors, broken service discovery, or surprise security exposures.

This post walks through the mental model for each driver, when to use it, and how to debug the most common problems.

Mental Model

Think of every Docker container as a tiny VM with its own network namespace. A network driver decides how that namespace is wired to the outside world.

  • Bridge: containers get private IPs on a virtual Linux bridge; outbound traffic is NAT’d through the host.
  • Host: the container shares the host’s network namespace directly. No NAT, no isolation.
  • Overlay: a virtual L2 network stretched across multiple Docker hosts using VXLAN tunnels.
Bridge:
[container]--veth--[docker0 bridge]--NAT--[host eth0]--> Internet

Host:
[container] === [host eth0] -> Internet   (no namespace boundary)

Overlay (Swarm/K8s-style):
[container A]--veth--[overlay net]==VXLAN==[overlay net]--veth--[container B]
     host 1                                       host 2
Bridge vs host vs overlay

Hands-on Example

Create a user-defined bridge network. The default bridge is functional but lacks automatic DNS resolution between containers, so almost always prefer a named one.

docker network create --driver bridge app-net
docker run -d --name api --network app-net nginx
docker run -it --rm --network app-net alpine sh -c "ping -c1 api"

Inside the second container, api resolves automatically because Docker embeds a DNS resolver on user-defined bridges.

For host networking, drop the namespace entirely:

docker run --rm --network host nginx

Now nginx binds directly to the host’s port 80. This is faster (no NAT, no veth) but two containers cannot both claim port 80, and there is no isolation.

For multi-host workloads, initialize a Swarm and create an overlay:

docker swarm init
docker network create --driver overlay --attachable web-overlay
docker service create --name web --network web-overlay --replicas 3 nginx

Containers scheduled on different nodes can now reach each other by service name as if they were on the same LAN.

Common Pitfalls

Using the default bridge. Containers on bridge cannot resolve each other by name. Always create a named bridge for multi-container apps.

Port publishing confusion. -p 8080:80 publishes container port 80 to host port 8080 on bridge networks. On --network host the -p flag is silently ignored — the container already uses the host’s interfaces.

MTU mismatches on overlay. VXLAN adds 50 bytes of overhead. If your underlay MTU is 1500, the overlay MTU must be 1450 or fragmentation breaks long-lived TCP connections. Set it explicitly:

docker network create --driver overlay --opt com.docker.network.driver.mtu=1450 web-overlay

Firewall rules. Overlay requires UDP 4789 (VXLAN), TCP/UDP 7946 (gossip), and TCP 2377 (Swarm management). Cloud security groups block these by default.

iptables surprises. Docker writes its own iptables chains. If you flush iptables manually, container connectivity breaks until Docker rewrites the rules.

Practical Tips

Inspect a network to see attached containers and IPAM:

docker network inspect app-net

When troubleshooting, exec into a container with diagnostic tools:

docker run --rm --network container:api nicolaka/netshoot ip addr

The --network container:api flag joins another container’s namespace, so you can sniff traffic, run dig, or trace routes without modifying the target image.

For production multi-host setups, consider whether you actually need raw overlay. Kubernetes CNIs (Calico, Cilium) replace Docker overlay entirely and add features like network policy and observability.

Keep an eye on subnet collisions. The default bridge uses 172.17.0.0/16, and user-defined bridges allocate from 172.18.0.0/16 upward. If those overlap with your corporate VPN, container traffic gets blackholed. Override with --subnet:

docker network create --subnet 10.50.0.0/24 app-net

Wrap-up

Pick bridge for single-host multi-container apps, host when raw throughput or low latency matters more than isolation, and overlay when containers on different hosts need to talk as if they shared a LAN. Always create user-defined networks instead of relying on the default bridge, watch MTU when tunneling, and remember that Docker quietly manages a lot of iptables state for you. Once you can sketch where the veth pairs and NAT rules live, every weird connectivity bug becomes much easier to reason about.