Host, none, and overlay
The bridge driver is the default because it's the right answer most of the time. The other modes exist for cases where its two costs — a NAT hop and a namespace boundary — are either unaffordable or actively in the way.
NETWORK ID NAME DRIVER SCOPE
9f1a2b3c4d5e bridge bridge local
1a2b3c4d5e6f host host local
2b3c4d5e6f7a none null local
Three networks exist on a fresh install, and SCOPE is the column that matters later: local means the network exists on this host only.
--network host: no namespace at all
The container gets no network namespace of its own. It uses the host's — the host's interfaces, the host's addresses, the host's routing table, the host's ports.
Nothing is published, because there's nothing to publish to. nginx binds port 80 and that is the host's port 80:
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=9214,fd=6))
The process shows as nginx on the host, with a normal host PID, listening on every host address. -p is silently ignored in this mode, which produces a memorable confusion: a docker run --network host -p 8080:80 that "ignores the port mapping." It isn't ignoring it; there's no NAT layer left for it to configure.
What you gain is the removal of a hop. No DNAT, no bridge, no veth traversal — measurable for a proxy handling six-figure packet rates, irrelevant for almost everything else. What you lose is worth more than most people expect:
- Port conflicts come back. Two containers can't both bind 80. The isolation that let you run ten copies of the same image is gone.
- Every listening socket is exposed on every host interface, including public ones. A container that binds
0.0.0.0:6379on a cloud VM has published Redis to the internet, and there's no-p 127.0.0.1:to prevent it. - It's Linux-only. On Docker Desktop the containers run inside a Linux VM, so "the host" is that VM, not your laptop — a difference that makes host mode behave completely differently in development than in production.
The legitimate uses are narrow: a container that needs to see the host's real interfaces (a monitoring agent reading NIC statistics, a DHCP or mDNS service that depends on broadcast traffic), or a network appliance where the extra hop genuinely matters. Reaching for it because port mapping is confusing is a bad trade.
--network none: a stack with nothing in it
A namespace with loopback and nothing else. No veth, no route, no way in or out.
This is the strongest isolation Docker offers and it's genuinely useful for batch work that touches only mounted files — an image resizer, a video transcoder, a build step. If the process is compromised, it has no network to exfiltrate anything over.
It's also a useful diagnostic. When you suspect a container is making network calls it shouldn't, running it with --network none turns silent background traffic into loud, obvious errors.
Overlay: containers across multiple hosts
Everything so far breaks the moment you have two machines. Both hosts hand out 172.17.0.2. Neither host's bridge knows anything about the other's containers. There's no route between them, and no way to write one that isn't ambiguous.
The overlay driver solves this by tunnelling. Container traffic is encapsulated in VXLAN — the original Ethernet frame is wrapped in a UDP packet, sent across the physical network to the other host, unwrapped, and delivered to the destination container's bridge. The underlying network only ever sees ordinary UDP between two host addresses; the containers see a flat Layer 2 network they appear to share.
NETWORK ID NAME DRIVER SCOPE
9f1a2b3c4d5e bridge bridge local
kx82n1p4qw7v appnet overlay swarm
1a2b3c4d5e6f host host local
SCOPE: swarm is the difference — this network's definition is shared across every node in the cluster, and a container attached to it on host A can reach one on host B by name.
Two properties of tunnelling are worth carrying forward, because they show up again in Kubernetes with different names:
Encapsulation costs MTU. A VXLAN header is 50 bytes on top of the original frame. If the physical network's MTU is 1500 and the container thinks its MTU is also 1500, a full-size packet becomes 1550 bytes on the wire and has to be fragmented — or, worse, gets dropped by something that won't fragment. Overlay networks therefore run a smaller MTU inside, and when that isn't configured correctly you get the classic signature: small requests work, large responses hang. Everything from the MTU and fragmentation articles applies directly, and this is where it stops being theoretical.
The underlay has to allow the tunnel. Docker's documentation lists three requirements between participating hosts: UDP 4789 for the overlay traffic itself, TCP and UDP 7946 for node-to-node communication, and TCP 2377 for the swarm control plane. A firewall or cloud security group that blocks any of those produces containers that start normally, join the network normally, and can't talk — with no error anywhere, because from the container's point of view its packets are simply lost.
Diagnose an overlay from the underlay
When containers on an overlay can't reach each other, testing between containers tells you nothing useful — the failure is one layer down. Test the hosts instead:
If you see VXLAN packets leaving one host and nothing arriving at the other, the problem is a firewall or security group between them, and no amount of container-level debugging will find it.
Choosing between them
| Mode | Isolation | Reachable from outside | Multi-host | Reach for it when |
|---|---|---|---|---|
| User-defined bridge | Own namespace, own subnet | Only via published ports | No | Almost always |
| Default bridge | Own namespace, shared subnet | Only via published ports | No | Never deliberately — it has no DNS |
host |
None | Every port the process binds | No | The extra hop genuinely matters, or the container needs the host's real interfaces |
none |
Total | Not at all | No | Batch work that shouldn't have network access |
overlay |
Own namespace | Via published ports on any node | Yes | Containers on different hosts must talk directly |
The honest summary is that a user-defined bridge covers the overwhelming majority of single-host work, and once you need more than one host, an orchestrator's networking replaces this decision entirely.
Practice
- Run the same image with
--network bridgeand--network host, and compareip -br addrinside each. Then checkss -tlpnon the host in both cases and explain what changed. - Try to start two containers in host mode that both bind port 8080. Note the error, and say which layer produced it.
- Run a container with
--network noneand attempt to install a package inside it. Then run the same image on a bridge network and compare. - On a two-node swarm (two VMs are enough), create an overlay network, run a container on each node, and confirm they can reach each other by name. Then capture UDP 4789 on one node while they talk.
- On that same overlay, compare
ip link showinside a container with the host's MTU. Work out the largest payload that fits without fragmentation, and test it withping -M do -s.
Exercise 5 is the bridge to what comes next. Kubernetes takes overlay networking as a baseline assumption — every pod gets a routable address on a cluster-wide network — and then adds something the Docker model has no equivalent for: a stable virtual address that outlives the containers behind it.
Sources
- Docker Docs, Host network driver
- Docker Docs, Overlay network driver
- Docker Docs, None network driver
- IETF, RFC 7348 – Virtual eXtensible Local Area Network (VXLAN)