Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Tech

How Container Networking Actually Works

A deep dive into the Linux kernel features that power container networking: bridges, network namespaces, iptables NAT, DNS resolution, and VXLAN overlays. Understand the real data path between containers to debug issues and control your infrastructure.

July 2026 8 min read 2 views 0 hearts

When you run a container, you probably think of it as a tiny virtual machine. But it's not. It's a process — just like any other program running on your host. And networking for containers? It's a clever set of tricks using Linux kernel features that have been around for decades.

Let's strip away the abstractions and look at what actually happens when one container talks to another.

The Bridge That Makes It Happens

Every Docker host has a virtual network bridge called docker0 by default. Think of it as a software switch inside your machine. When you start a container, Docker creates a virtual Ethernet pair — one end inside the container (eth0), the other attached to this bridge (vethXXXXX).

Here's the key insight: containers on the same bridge can talk to each other directly, just like devices plugged into the same physical switch. No port forwarding, no NAT between them.

# See the bridge
ip link show docker0

# List all veth pairs attached
bridge link show

If you run those commands on a host with running containers, you'll see the magic. Each veth interface is the host-side of a virtual cable plugged into your container.

The Namespace Trick

Containers don't share the host's network stack. Instead, each container gets its own network namespace. This is a Linux kernel feature that isolates network interfaces, IP addresses, routing tables, and firewall rules.

When you run docker run --network host, you're actually saying "skip the namespace — share the host's network directly." That container can use ports without mapping, but it also has zero isolation.

Every other container gets a private copy of the network stack. The virtual Ethernet pair connects this isolated namespace to the host's bridge. Traffic flows through that pair — in and out.

Port Mapping: The NAT You Didn't Know You Had

When you do -p 8080:80, Docker adds an iptables rule. Actually, it adds several. Here's what happens:

  1. A DNAT rule in the PREROUTING chain rewrites packets coming to your host's port 8080, changing the destination to the container's IP and port 80.
  2. A corresponding rule in the FORWARD chain allows traffic between the bridge and the outside world.
  3. A MASQUERADE rule handles return traffic so the container sees the host as the source.

You can see these rules with:

sudo iptables -t nat -L -n

Look for the DOCKER chain. Those rules make containers reachable from outside, even though they have private IPs like 172.17.0.2.

Container-to-Container Communication

Containers on the same host find each other by IP. But IPs change when containers restart. That's why Docker has built-in DNS.

When you create containers on a user-defined network (not the default bridge), Docker runs a tiny DNS server embedded in the host. Containers query 127.0.0.11 (loopback inside the container namespace) which is intercepted and resolved by Docker's embedded DNS.

So ping my-mongo-container works because Docker translates that container name to its current IP. The default bridge doesn't have this — only custom networks do.

Overlay Networking for Multi-Host

When containers run on different physical machines, you need overlay networks. Docker uses VXLAN under the hood. Every host runs a key-value store (like etcd or Consul) that maps container IPs to host IPs.

When container A (on host 1) sends a packet to container B (on host 2), the packet gets: - Encapsulated in a UDP packet with VXLAN headers - Sent over the physical network to the other host - Decapsulated and delivered to the target container

The hosts themselves create VXLAN Tunnel Endpoints (VTEPs) that handle this encapsulation. From the container's perspective, it's just normal Ethernet traffic.

The Data Path: End to End

Let's trace a real example. Container A (172.17.0.2) pings container B (172.17.0.3) on the same host:

  1. Container A's process sends an ICMP packet out its eth0
  2. The veth pair carries it to the host's docker0 bridge
  3. The bridge looks at the destination MAC and sees it belongs to another veth port
  4. It forwards the packet to container B's veth endpoint
  5. Container B's network stack receives it normally

Now outside traffic hitting port 8080:

  1. Packet arrives at host's physical interface (eth0)
  2. PREROUTING iptables rule changes destination to 172.17.0.3:80
  3. Routing sends it to docker0 bridge
  4. Bridge delivers to container's veth pipe
  5. Process inside container receives the connection

Why This Matters for Developers

Understanding this stack helps you debug real problems:

  • "Connection refused" when you mapped the port? Check iptables isn't overwriting Docker's rules.
  • DNS resolution failing between containers? They're probably on the default bridge. Use a custom network.
  • High latency between containers on different hosts? Your overlay might be encapsulating too much — consider host networking for performance-critical paths.

Container networking isn't magic. It's Linux networking with convenient labels. Once you see the veth pairs, the bridges, and the iptables chains, the abstraction melts away. And that's when you truly control your infrastructure.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.