The core idea
Bridge networks give each container its own isolated network stack. Two modes skip that:
--network host: no network namespace. The container uses the host's network directly.--network none: a network namespace with nothing in it but loopback.
And one mode borrows: --network container:NAME joins another container's network namespace.
none: nothing in, nothing out
$ docker run --rm --network none alpine sh -c 'ip -4 addr | grep inet; wget -qO- -T 3 http://example.com'inet 127.0.0.1/8 scope host lowget: bad address 'example.com'
Only lo. Useful for jobs that should never touch the network: processing untrusted files, offline batch work, or
proving that a build doesn't secretly download anything.
host: the machine's network
With --network host, a server listening on port 80 in the container listens on port 80 of the host. No NAT, no
-p; Docker even warns if you pass one:
$ docker run --rm -p 9999:80 --network host alpine trueWARNING: Published ports are discarded when using host network mode
On a Linux server, this is the real host network: slightly less overhead, and handy for software that needs many ports or sees the host's interfaces. The cost is isolation: port clashes with the host and other containers, and the container can reach every service listening on the host.
On Docker Desktop, "the host" is the Linux VM, not your Mac:
$ docker run --rm --network host alpine sh -c 'ip -4 addr | grep inet | head -2; hostname'inet 127.0.0.1/8 scope host loinet 192.168.65.3/24 brd 192.168.65.255 scope global eth0docker-desktop$ docker run -d --name hostweb --network host nginx:alpine$ curl -m 3 localhost:80curl: (7) Failed to connect to localhost port 80 after 0 ms: Couldn't connect to server
nginx is listening, but on the VM's port 80, which your Mac can't see. Recent Docker Desktop versions have an opt-in
host networking setting; without it, use -p on Mac and Windows. This is a classic "works on my Linux box, not on my
Mac" difference.
container: borrow a network
--network container:NAME puts a new container into an existing container's network namespace. They share
interfaces, IP and localhost:
$ docker run --rm --network container:web1 alpine wget -qO- http://127.0.0.1 | grep -o '<title>.*</title>'<title>Welcome to nginx!</title>
127.0.0.1 reached nginx, because "localhost" is now the nginx container's. This is how you debug a container that
has no tools of its own, like a distroless image: attach a toolbox container to its network (05.04 Debugging network problems).
It's also how Kubernetes pods work: all containers in a pod share one network namespace.
| Mode | Own network stack | Reachable via -p | Typical use |
|---|---|---|---|
| user-defined bridge | yes | yes | almost everything |
host | no, uses the host's | n/a, already on the host | Linux-only performance or port-heavy tools |
none | yes, loopback only | no | jobs that must stay offline |
container:NAME | shares another's | via the other container | debugging, sidecars |
On a Mac, you run a web server with --network host and can't reach it at localhost from your browser. Why?
Run alpine ip addr with --network none, the default, a user-defined network and --network host, and compare the interfaces. Then start nginx and use --network container: to fetch its page via 127.0.0.1.
STUCK? ▸
On Linux, the host-mode nginx is reachable at localhost:80 unless something else already uses port 80, in which case it exits with "address already in use".
Recap
Interview questions
What are the trade-offs of --network host?