sehaj/learn
Docker/05 Networking

05.03 · with code · 9 min

Host and none networks

The two network modes that skip the bridge: host shares the machine's network, none has no network at all. Plus how to borrow another container's network for debugging.

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

❯terminal
$ 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 lo
wget: 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:

❯terminal
$ docker run --rm -p 9999:80 --network host alpine true
WARNING: 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:

❯terminal
$ docker run --rm --network host alpine sh -c 'ip -4 addr | grep inet | head -2; hostname'
inet 127.0.0.1/8 scope host lo
inet 192.168.65.3/24 brd 192.168.65.255 scope global eth0
docker-desktop
$ docker run -d --name hostweb --network host nginx:alpine
$ curl -m 3 localhost:80
curl: (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:

❯terminal
$ 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.

ModeOwn network stackReachable via -pTypical use
user-defined bridgeyesyesalmost everything
hostno, uses the host'sn/a, already on the hostLinux-only performance or port-heavy tools
noneyes, loopback onlynojobs that must stay offline
container:NAMEshares another'svia the other containerdebugging, sidecars
Predict first

On a Mac, you run a web server with --network host and can't reach it at localhost from your browser. Why?

Commit to an answer before you read on.
CheckpointTry every mode

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

MidfreqGood to knowConcept

What are the trade-offs of --network host?

Report a mistakeEdit this page

Fundamentals you'll use