Home / Software y Cloud / Containers from the inside: namespaces, cgroups and the layers trick

Containers from the inside: namespaces, cgroups and the layers trick

Ilustración de tecnología de contenedores

More than “packaging software”

When you launch Docker, it feels like you have a small, fast virtual machine. In reality there is no virtual machine: a container is a normal Linux process running directly on the host kernel, but one that has been placed inside an “enclosure” so it believes it lives in its own machine. That illusion is the key to everything, and it is built on three fundamental kernel pieces: namespaces, cgroups and a layered file system (OverlayFS).

Namespaces: isolating what each process sees

A namespace is a Linux table that decides what a process can see. When you launch a container with docker run, the runtime creates several new namespaces so the process does not see the host system but its own isolated one instead:

  • PID namespace: the process sees its own process IDs. Inside the container, its first process is PID 1, just like in a real machine.
  • Network namespace: it has its own network interfaces, its own routing table and its own TCP/IP stack. That is why each container has its own IP address even though they share the same physical host.
  • Mount namespace: it controls which file systems it sees. The container mounts its own directory tree, not the host’s.
  • UTS, IPC and User namespaces: they isolate the hostname, the inter-process message queues and the user identifiers.

Cgroups: putting limits on greed

Namespaces isolate the view, but they do not limit resources. That is where cgroups (control groups) come in, the kernel mechanism that regulates how much CPU, memory, disk and network a set of processes may use. When you run docker run -m 512m --cpus=2, Docker translates those flags into a cgroup that limits the container’s consumption. That is what guarantees a container with a memory leak does not take down the whole server.

OverlayFS: the layered file system

This is the magic of images. A Docker image is not a full disk: it is a stack of read-only layers superimposed on an OverlayFS. Each Dockerfile instruction (each RUN, COPY, ADD) produces a new layer stacked on top of the previous ones. When the container is launched, a thin writable layer is added on top of all of them.

The performance trick is called copy-on-write: if the process wants to modify a file that lives in a lower layer, the system does not copy the whole layer; it copies only that file to the upper layer and leaves the rest intact. That is why containers share base layers (the same ubuntu or node) without duplicating space, and why launching a container is almost instantaneous: only existing layers are mounted, no disk is cloned.

The runtime and the daemon

Traditionally, dockerd (the daemon) received your commands and used the runc runtime to create containers. The communication protocol with the low-level layer is called OCI (Open Container Initiative), an open standard that defines the image format and the behavior of runtimes. Today there is containerd, an intermediate runtime that Docker, Kubernetes and others use as the container orchestration layer, making the ecosystem modular and decoupled.

Networking: connecting containers without chaos

Each container with its own network namespace would have to be isolated from the rest, but they need to communicate. Docker solves this with virtual bridge networks: it creates a virtual switch on the host and connects each container to it with veth pairs (a virtual cable with one end inside the container and the other on the bridge). Traffic between containers on the same network travels through the bridge without leaving the machine, and isolation is reinforced with iptables rules for port translation (DNAT).

Why this matters

Understanding that a container is just a process with namespaces, cgroups and file layers explains many things that seem like magic: why they start in milliseconds (there is no kernel to boot), why you cannot easily “ping” a container (isolated network), or why two containers with the same image share disk. This is not hardware virtualization: it is operating-system-level virtualization, which is why it is so lightweight. When one day an image refuses to start, knowing how to look inside those three mechanisms turns an apparently opaque problem into a set of concrete pieces you can inspect one by one.