Container Networking
The virtual switch under your pods
Containers get virtual NICs, bridges, and NAT by default: bridge network, port publishing, overlay for multi-host, and DNS-driven service discovery. Understanding the stack is debugging 'why can't my service talk to the other one'.
What you will learn
- Describe the default bridge/NAT container network
- Distinguish host, bridge, overlay, none, macvlan
- Debug connectivity: DNS, published ports, CNI paths
Each container gets a veth into a virtual bridge; outbound goes through NAT masquerade; inbound via published ports maps host:port → container:port. Kubernetes uses CNI (Calico/Cilium) + overlay for cross-node routing; DNS names resolve to addresses inside the network.
What is this?
Docker networks: bridge (default, isolated per network), host (bind directly), none (isolation), overlay (Swarm/K8s cross-host), macvlan (physical MAC). Mechanisms: veth pairs, Linux bridge, iptables DNAT/SNAT, container-local eth0, DNS embedded (127.0.0.11) for service/alias resolution. Port publishing: -p binds docker-proxy; explicit binds reduce surface. K8s/CNI: pod has its own IP; services abstract pods via ClusterIP/iptables or eBPF (Cilium); cross-node via overlay/VXLAN or direct routing. Network policies filter pod-to-pod traffic.
Why do you need it?
- Container IPs are ephemeral — DNS and services, not IPs, are the pointing model.
- Publishing 0.0.0.0 by accident exposes services to the world (and the insecure ones).
- Overlay choice (VXLAN latency, eBPF performance) shows up at the network layer.
- Multi-host 'can't connect' bugs are almost always name/DNS or CNI, not code.
Mental model
A co-working floor where each desk has a doorbell but the front desk does the mail
Bridge + NAT + DNS
Each office (container) has an inbox (eth0). The floor switch (bridge) links offices, mail routing hides real-world addresses (NAT), and the front desk looks up names for you (DNS).
How it works
- Runtime creates veth pair: one end inside container, one on the bridge.
- Default egress flows through NAT masquerade to the host's external IP.
- Published ports: DNAT host port → container IP:port; docker-proxy handles catch-all binds.
- Within a bridge network, containers reach each other by network alias/hostname.
- Overlays encapsulate cross-host traffic (VXLAN) or swap in eBPF for slower/packet-efficient datapaths.
Default container network.
Examples
Two containers talking by name
docker network create appnetdocker run -d --network appnet --name api -p 8080:8080 lab-app:1.0docker run -d --network appnet --name worker -e API_URL=http://api:8080 --entrypoint sh alpine -c 'apk add curl >/dev/null 2>&1; while true; do curl -s $API_URL; sleep 1; done'docker logs worker --tail 3 # hi (resolved "api" via bridge DNS)No IPs wired by hand: the bridge DNS turns 'api' into the container IP; the -p publishes the API externally.
In production
- Compose dev stacks: one bridge per app, clear aliases.
- K8s: services + CNI policies segment environments without manual firewall rules.
- Fargate/Cloud Run hide the overlay; service-to-service via internal endpoints.
Best practices
- Prefer explicit networks and service names over --link legacy or IP-address shortcuts.
- Bind published ports to 127.0.0.1 unless truly public.
- Use DNS-based service discovery; never hard-code kube/container ips.
- In K8s, apply NetworkPolicies early: default-deny and allow as needed.
- For production clarity, keep one concern per network/bridge.
Common mistakes
- -p 8080:80 but app listens on 8443 → 'connection refused', not a build bug.
- Two containers on different bridges assuming they can <service-name> each other.
- 0.0.0.0 publishes exposing debug endpoints on the public NIC.
- Forgetting overlay/large MTU issues causing slow or flaky cross-host transfers.
Debugging tips
- docker network inspect appnet → live IP/alias mappings.
- nsenter/exec into the container and use the same stack the app does (curl/python).
- Port sanity: docker ps shows the published mapping; test on the host with ss/nc.
- Multi-host issue? Check CNI status and VXLAN/tunnel health, then try nslookup inside the pod.
Interview checkpoint
Quick quiz
Default outbound container traffic to the internet is:
To expose a container port externally you: