How Containers Get Networking and Storage
Summary
- A container is a process wrapped in Linux namespaces and cgroups, so its network and filesystem are just kernel features scoped to that process.
- Insight: Networking and storage are not "built into" the image - they are attached by the runtime at start time and torn down when the container exits.
- Key Concepts: network namespace, bridge, veth pair, port publishing, union filesystem, volume, bind mount.
- When to Use: Read this before debugging "why can't my container reach the database" or "why did my data disappear" - both trace back to how attachment works.
- Limitations/Trade-offs: The Docker single-host model and the Kubernetes cluster model share primitives but differ sharply; do not assume one maps cleanly onto the other.
- Related Topics: Docker networking modes, user-defined networks, volumes, storage permissions.
Foundations
A container is not a virtual machine.
It is an ordinary Linux process that the kernel has isolated using namespaces (what it can see) and cgroups (what it can use).
Two of those namespaces produce everything in this section: the network namespace and the mount namespace.
The network namespace gives the process its own view of interfaces, routes, and iptables rules.
The mount namespace gives it its own view of the filesystem tree, assembled from image layers.
Because both are created fresh when the container starts, a container begins life with an empty network stack and a throwaway writable layer.
The runtime - Docker Engine on a laptop, containerd on a Kubernetes node - is responsible for populating them.
Storage follows the same logic.
The image is a stack of read-only layers; the runtime adds one thin read-write layer on top using an overlay filesystem (overlayfs).
Anything written there lives and dies with the container unless you attach durable storage explicitly.
Mechanics & Interactions
Consider networking on a single Docker host.
When a container joins the default bridge network, the runtime creates a veth pair: one end lands inside the container's network namespace as eth0, the other attaches to the host bridge docker0.
The container gets a private IP from the bridge subnet, and the host performs NAT so outbound traffic appears to come from the host address.
Inbound traffic is different: nothing outside can reach that private IP until you publish a port.
Publishing (-p 8080:80) installs a DNAT rule that forwards host port 8080 to the container's port 80.
docker run -d -p 8080:80 --name web nginx:1.27
curl http://localhost:8080So "exposing" a port in an image is only documentation; publishing is the act that actually opens a path.
Storage mechanics mirror this.
The writable overlay layer is fast but ephemeral, so durable data needs an explicit mount.
A named volume is storage the engine manages under its own directory and mounts into a path in the container.
A bind mount maps a specific host directory into the container, giving you direct, unmanaged access to host files.
docker volume create appdata
docker run -d -v appdata:/var/lib/app myapp:1.0The container writes to /var/lib/app, but the bytes live in the volume, so they survive docker rm.
Now shift to Kubernetes, where the primitives are the same but the topology changes.
Every Pod gets its own IP, and every container in a Pod shares that one network namespace - which is why they reach each other over localhost.
The IP itself is assigned by a CNI plugin (Calico, Cilium, and others), not by Docker; Kubernetes nodes run containerd via the CRI, and Docker Engine is not the in-cluster runtime.
Storage in Kubernetes is abstracted behind PersistentVolumeClaim, which a CSI driver binds to real disk from a cloud or storage backend.
Advanced Considerations & Applications
The single biggest source of confusion is the jump from one host to a cluster.
On one Docker host, port publishing and NAT are how you reach a container from outside.
In Kubernetes, Pod IPs are routable inside the cluster but not stable, so you never target them directly - you put a Service in front for a stable virtual IP and DNS name.
External reach then comes from a Service of type LoadBalancer, an Ingress, or the newer Gateway API, not from publishing a port.
Storage has a parallel jump.
A bind mount to a host path works on one machine, but in a cluster a Pod can be rescheduled to a different node where that path does not exist or holds different data.
That is why cluster storage uses network-attached volumes through CSI, and why hostPath is treated as a security-sensitive escape hatch rather than a normal tool.
Lifecycle is the unifying idea to carry into production.
Networking is attached at start and released at stop; storage is ephemeral unless you deliberately bind it to a durable backend.
Design stateless workloads so a lost container costs nothing, and route all real state into managed volumes or external datastores.
Common Misconceptions
"Data is saved inside the image." No. Images are read-only. Runtime writes go to the ephemeral layer and vanish on removal unless a volume is mounted.
"EXPOSE opens the port." No. EXPOSE is metadata. Only publishing (-p) or a Kubernetes Service actually routes traffic in.
"Containers on different hosts can just talk over their container IPs." No. Bridge IPs are host-private. Cross-host traffic needs an overlay network or the Kubernetes cluster network.
"Docker runs my pods." No. Kubernetes nodes use containerd through the CRI; dockershim was removed. Docker is for build and local dev.
"A bind mount and a volume are interchangeable." They overlap but differ: volumes are engine-managed and portable; bind mounts couple you to a specific host path and its permissions.
FAQs
Why can my container reach the internet but nothing can reach it? Outbound uses NAT automatically; inbound needs an explicit published port or a Service.
Where does my data go if I do not mount a volume? Into the container's writable overlay layer, which is deleted when the container is removed.
Do containers in the same Pod share storage too? They can share a volume you mount into each, and they always share the network namespace.
Is localhost inside a container the host machine?
No. It is the container's own loopback (or the Pod's, in Kubernetes), not the host.
Why does Kubernetes not use port publishing? Because Pods are ephemeral and multi-node; Services and Ingress/Gateway provide stable, routable entry points instead.
Related
- Docker Networking Basics
- User-Defined Networks
- Volumes & Bind Mounts
- Storage Permissions Pitfalls
- Networking & Storage Best Practices
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).