The Runtime Theory
mediumApplicationDSA#operating-systems#virtualization#containers

How do containers isolate processes without virtualization?

Tests whether you know the kernel primitives. A strong answer names namespaces (isolated views) and cgroups (resource limits) and explains that isolation is a kernel feature, not a machine.

The Runtime Theory Team2 min readasked at google · amazon · cloudflare · netflix

This question tests whether you know the primitives by name. The interviewer wants clone flags and cgroup controllers — not "containers are lightweight VMs."

The mental model: a container is a set of ordinary processes on the host kernel. What makes it a container is two kernel mechanisms applied at creation and runtime: namespaces change what a process can see, and cgroups change how much it can use. Virtualization emulates hardware; containers just rewire kernel interfaces.

Walk through the mechanism. When Docker (via runc) launches a process, it calls clone() with namespace flags: CLONE_NEWPID (the process sees itself as PID 1 in a fresh PID namespace; the host still tracks its real PID), CLONE_NEWNS (a private mount table — the image root is staged with pivot_root), CLONE_NEWNET (its own network stack: loopback, interface, routing table, iptables — traffic flows out through a veth pair and a bridge or NAT), plus UTS (hostname), IPC, and optionally user (UID remapping) namespaces. Every syscall that reports system state — getpid, mount, getsockname, sethostname — answers from the namespace the process belongs to. That's the entire trick: isolation is implemented inside the syscalls.

Limits come from cgroups (v2). The container's processes are members of a cgroup with controllers attached: cpu.max (quota/weight against the CPU), memory.max (a hard limit — when the cgroup hits it, reclaim runs inside the cgroup and, failing that, the cgroup's processes are OOM-killed, not arbitrary ones), pids.max, and io.max (block I/O throttling). The kernel enforces these on every allocation and wakeup, so a container can't take more than its share.

Why it's not a VM: one kernel, shared page cache, shared syscall interface, no hypervisor, no guest boot, no second scheduler — which is why containers are cheap to start and dense to run. The price is the boundary: a VM's isolation is hardware; a container's is a set of kernel interfaces, one kernel bug away from the host.

Tradeoffs and edge cases worth naming:

  • Root in a container is host root unless user namespaces remap it — the classic security surprise.
  • Namespaces are a view, not a guarantee: shared /proc data, kernel globals, and shared page cache leak information.
  • seccomp and AppArmor sit on top: they filter the syscalls a container may even attempt.
  • A cgroup memory limit kills the container's processes, so tuning limits to the workload is an operational skill.

A strong closing line: containers are processes whose syscalls lie about system state via namespaces and whose resource use is metered via cgroups — same kernel, no emulation, and the isolation is only as strong as the kernel interface it rides on.

This answer walks

Follow-ups they'll push on

  1. 01What can a container not isolate?
  2. 02How does a container get its own network stack and IP address?
  3. 03Why is a container escape worse than a VM escape?

More interviews in this topic

One dispatch a week

The trace behind each question, the tradeoff that explains it, and one technical dispatch per week — no noise.

One technical dispatch per week. No noise.