Chapter 7 of 16 · Visual guide

Networking: namespaces and isolated stacks

Docker does not invent isolation. It asks the Linux kernel for a fresh network namespace for every container.

key idea / Docker itselfcontainer / good pathhost / watch outproblem / blockedneutral

What a container really is

A container is an ordinary process wrapped in namespaces.

A container is a process with namespacesLinux namespaces give a process its own view of processes, network, mounts, hostname, IPC and users.pidown process treenetown network stackmntown filesystem viewutsown hostnameipcown shared memoryuserown user IDsContainer = a process + these namespaces + cgroups for CPU and memory limits
The net namespace is the one this whole networking track is about.

A private network stack per container

One host, two private network stacksThe host has its own namespace. Containers A and B each have a separate namespace with their own loopback, eth0, IP and routing table.Host (root network namespace)host stack: eth0 192.168.1.20 · docker0 172.17.0.1 · iptablesContainer A namespacelo 127.0.0.1eth0 172.17.0.2own routes · own firewall rulesnginx listening on :80Container B namespacelo 127.0.0.1eth0 172.17.0.3own routes · own firewall rulesnginx listening on :80
Both containers listen on :80 and nothing collides, because each one has its own port table.

Why localhost differs

localhost is per containerIn container A localhost:80 reaches A own nginx. In container B localhost:80 is refused because B has no listener.Container Acurllocalhost:80nginx :80200 OK: A talks to itselfContainer Bcurllocalhost:80no listenerrefused: B never sees A

Sealed rooms need a door

Namespaces are sealed roomsA container namespace needs a virtual cable to reach the host namespace. The next chapters cover that cable.Container namespaceeth0 172.17.0.2one end of a virtual cableHost namespacevethXXXXother end, plugged into docker0veth pair
A sealed room needs a door. Chapter 10 builds it: a veth pair.

Try it yourself

Alpine does not include ip until you add it. On Docker Desktop, docker0 lives in the Linux VM, so compare addresses with docker exec, not with the Mac’s ifconfig.

  1. Step 1 · Start a container and install the tool
    $ docker run -d --name box --rm alpine:3.20 sleep 300
    $ docker exec box apk add --no-cache iproute2
  2. Step 2 · The container’s interfaces

    lo is loopback. eth0 is this container’s address, usually on 172.17.0.0/16.

    $ docker exec box ip addr
    1: lo:  inet 127.0.0.1/8
    2: eth0@if12:  inet 172.17.0.2/16
  3. Step 3 · Its route is not the host’s route
    $ docker exec box ip route
    default via 172.17.0.1 dev eth0
    172.17.0.0/16 dev eth0 scope link
  4. Step 4 · A second container has a different eth0
    $ docker run -d --name box2 --rm alpine:3.20 sleep 300
    $ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' box2
    172.17.0.3
    $ docker stop box box2

Recap

Quick check

Two containers both run nginx on port 80 on the same host. Why is there no port conflict?
Show answer

Each container has its own network namespace and therefore its own port table. The conflict would appear only if both were published on the same host port, or if both ran with --network host.