Tech
How Docker Works: Understanding Containers, Namespaces, and cgroups
Explore the internal mechanics of Docker to understand how it uses Linux namespaces, control groups, and UnionFS to create isolated processes without the overhead of virtual machines.
June 2026 · 5 min read · 1 views · 0 hearts
Advertisement
Imagine you’re trying to move a house. Instead of throwing everything into a truck haphazardly and hoping the couch fits through the door of the new place, you pack everything into standardized shipping containers. No matter what ship, crane, or truck handles the container, the contents inside remain exactly the same.
Docker does this for software. But while we talk about "containers" as if they are lightweight virtual machines, they aren't VMs at all. There is no guest OS, no hypervisor, and no hardware emulation.
Here is exactly what is happening behind the scenes when you run docker run.
The Big Lie: Containers Aren't "Real"
First, the most important technical distinction: A container is not a physical thing.
Unlike a Virtual Machine (VM), which is a complete slice of hardware (CPU, RAM, Disk) running its own kernel, a Docker container is simply a isolated process running on the host's Linux kernel.
If you run ps aux on your host machine, you will see the processes running inside your containers listed right alongside your browser and text editor. The "container" is just a set of fences built around that process to make it feel like it's on its own isolated machine.
The Three Pillars of Docker Isolation
Docker achieves this "illusion" of isolation using three core features of the Linux kernel.
1. Namespaces (The Blinders)
Namespaces are what keep containers from seeing each other. Think of them as blinkers on a horse; the process can only see what the kernel allows it to see.
- PID Namespace: The container thinks it is the only process running. Inside the container, the main app is
PID 1. Outside, the host sees it asPID 4502. - NET Namespace: Each container gets its own virtual network stack, IP address, and routing table.
- MNT Namespace: The container has its own view of the file system. It thinks
/is the root of its world, unaware that it's actually just a folder buried deep in the host's storage. - UTS Namespace: Allows the container to have its own hostname.
2. Control Groups (cgroups) (The Resource Police)
If namespaces stop a process from seeing other things, cgroups stop a process from eating all the resources.
Without cgroups, one buggy container could trigger a memory leak that crashes your entire server. Cgroups allow Docker to set hard limits: "This container gets exactly 512MB of RAM and 10% of the CPU." If the container tries to exceed these limits, the kernel steps in and throttles it (or kills it via the OOM Killer).
3. Union File Systems (The Layer Cake)
This is the secret to why Docker images are so small and start so fast. Docker uses a UnionFS (like OverlayFS).
Instead of copying a full OS every time you create an image, Docker uses layers. * Layer 1 (Base): A slim version of Ubuntu (Read-only). * Layer 2 (Dependencies): Python installed on top (Read-only). * Layer 3 (Your App): Your code copied in (Read-only).
When you start a container, Docker adds a thin Writable Layer on the very top. If your app writes a file to /tmp, it doesn't change the image; it writes to this top layer. When the container is deleted, the writable layer vanishes, but the read-only image layers remain perfectly intact for the next container to use.
The Workflow: From Dockerfile to Process
To put it all together, here is the lifecycle of a container:
- The Build: You write a
Dockerfile. Docker executes these instructions one by one, creating a read-only layer for each step. This is the Image. - The Request: You run
docker run. The Docker Daemon (the brain) looks for the image locally; if it isn't there, it pulls it from a registry. - The Creation: Docker creates a writable layer on top of the image and assigns a set of Namespaces and cgroups to the process.
- The Execution: The kernel starts the process. The process "believes" it is running on its own private Linux server, even though it's just a restricted process sharing the host's kernel.
Summary: VM vs. Container
| Feature | Virtual Machine | Docker Container |
|---|---|---|
| OS | Full Guest OS (GBs) | Shared Host Kernel (MBs) |
| Boot Time | Minutes | Milliseconds |
| Isolation | Hypervisor (Hardware level) | Namespaces/cgroups (OS level) |
| Efficiency | High overhead | Near-native performance |
Advertisement
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.