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
/procdata, 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.