4.2.41 · D1Operating Systems

Foundations — Containers — namespaces, cgroups, difference from VMs

2,225 words10 min readBack to topic

Before you can understand namespaces, cgroups, or "container vs VM," you must own a handful of words that the parent note threw around freely. We build each from zero: plain meaning → the picture → why the topic needs it, in an order where every item leans on the one before.


1. Program, process, and PID

The picture. Think of a program as a recipe card, and a process as one cook actually cooking it right now. Two cooks can follow the same recipe → two processes, same program, different PIDs.

Why the topic needs it. A container is a process (or a small group of them). Everything the parent note says — "PID 1", "put the PID into cgroup.procs", "echo $$" — is talking about these numbered live cooks. If you don't picture a process as a numbered running thing, "the container's first process becomes PID 1" is gibberish.

Recall What is

$$ in the shell? $$ expands to the PID of the current shell — a quick way to say "this very process". echo $$ prints your own process number.

Related vault reading: Processes and the clone/fork syscall.


2. The kernel and its global tables

The picture. The kernel is the building manager who holds the master ledgers. There is normally exactly one copy of each ledger for the whole machine:

  • one list of PIDs (every running process),
  • one hostname ("what this machine is called"),
  • one mount table (which disks appear where in the folder tree),
  • one network stack (the cards, IP addresses, ports).

Why the topic needs it. A namespace is defined as "a private copy of one of these global tables." You cannot understand "a private copy" until you can point at the single shared original. And "one kernel = container, many kernels = VM" only makes sense once you see the kernel as the manager holding the ledgers.

Related vault reading: Linux Kernel — syscalls.


3. Syscall — how a program asks the kernel

The picture. Imagine a locked service window. Your program slides a request slip ("clone, please, with these options") through the window; the kernel does the privileged work behind the glass and slides back a result.

Why the topic needs it. The three container-making mechanisms in the parent — clone, unshare, setns — are all syscalls. "Turn a process into a container" literally means "make the right syscalls." Without the word syscall, that whole machanism section is floating.


4. clone / fork / unshare / setns

The picture. Think of shared ledgers again:

  • clone(CLONE_NEWPID) = "make me a child, and hand it a blank new PID ledger."
  • unshare = "I'll stay here, but tear my page out of the shared ledger and start my own."
  • setns = "let me flip to that group's ledger and write alongside them." This is exactly how docker exec steps into a running container.

Why the topic needs it. These are the only ways private tables come into existence. The parent's claim — "OR the flags together and the process names nothing shared → full isolation" — is just: choose which ledgers get privatised, one flag per ledger.

Related vault reading: Processes and the clone/fork syscall.


5. Flags — one bit per switch

The picture. Picture a row of light switches. Each switch = "give a fresh copy of one table." Flip NEWPID and NEWNET, leave the rest off → new PID list and new network stack, but the same hostname and mounts as the host. The parent's "OR them together" is: press several switches in the same trip.

Why the topic needs it. This is the knob that lets containers be partial — you can isolate the network but share everything else. Understanding "one flag = one privatised table" is the whole derivation of why namespaces are enough.


6. The filesystem tree, /, mount, and chroot

The picture. A single tree growing from /. Mounting a USB stick at /media/usb grafts a new branch there. A mount namespace gives a process a whole private tree, so its / can be a completely different set of folders (this is how a container gets its own root filesystem).

Why the topic needs it. The parent lists a Mount namespace ("own root /"). To feel it, you must already see / as the trunk of a tree that can be swapped per process.

Related vault reading: Filesystems — mount and chroot and, for how images stack many read-only layers into one /, Docker images and layered filesystems (overlayfs).


7. Network words: interface, IP, port, bridge

The picture. A network namespace hands a process its own set of these — its own cards, its own IPs, its own port 80. Two containers can both "listen on port 80" without clashing, because each has a private network stack.

Why the topic needs it. The Network namespace row in the parent table names exactly these four. Related vault reading: Networking — virtual interfaces and bridges.


8. UID / GID and "root"

The picture. A user namespace builds a translation table: "inside, you are UID 0 (root); outside, you are really UID 100000 (a nobody)." So container-root looks mighty inside its curtained room but is powerless in the real house.

Why the topic needs it. The parent's third steel-man ("root inside = root outside") is only debunked once you can picture a UID mapping. Without UID as "which numbered user am I", that fix is empty.


9. Resources, quota, and period (the cgroup numbers)

The picture. Picture a prepaid meter. Every period microseconds the kernel tops up your quota microseconds of CPU time. Spend it early → you're frozen until the next refill.

Why the topic needs it. This is the only real formula in the whole parent note. It rests on knowing that CPU time is a resource measured in microseconds, refilled per period. Related vault reading: Scheduling — CFS and CPU shares.


10. Virtual machine and hypervisor (the contrast partner)

The picture. Where a container is a curtained room in one house (one kernel), a VM is a whole second house next door with its own plumbing (its own kernel). Heavy, slow to build, but the walls are real.

Why the topic needs it. The entire "Containers vs VMs" section is a comparison — you can't compare against a word you don't hold. Related vault reading: Virtualization and Hypervisors (Type 1 vs Type 2).


How these feed the topic

Program vs Process and PID

Kernel and its global tables

Syscall - the service window

clone unshare setns

Namespaces - private copy of a table

Flags - one switch per table

Filesystem tree and mount

Interface IP port bridge

UID GID and root

Resource quota period

Cgroups - caps on usage

Container = process lied to and limited

VM and hypervisor

Container vs VM comparison

Read top to bottom: process + kernel give you the thing being isolated and the tables that are isolated; syscalls + flags are the tools that make private copies; those copies are namespaces; quota/period on top of a process are cgroups; put the two together and you have a container, which you then contrast with a VM.


Equipment checklist

Test yourself — you're ready for the parent note when you can answer each aloud.

A program vs a process
program = dead file on disk; process = that program running, with a live PID
What a PID is
a positive integer naming one running process
What the kernel holds that namespaces copy
single global tables — PID list, hostname, mount table, network stack
What a syscall is
the doorway a program uses to ask the kernel for a privileged service
Difference: clone vs unshare vs setns
clone = make child with fresh tables; unshare = current process gets own; setns = join an existing one
What a flag like CLONE_NEWPID does
switches on a fresh private copy of exactly one table (here the PID list)
What / means
the root, the top folder of the filesystem tree
What mount does
attaches a disk's contents at a folder so it appears in the tree
UID 0 is
root, the all-powerful user; a user namespace can map it to a powerless host UID
quota and period give what
CPU share as the fraction quota/period of one core
"50000 100000" as a CPU share
50000/100000 = 0.5 → half of one core
"50000 200000" as a CPU share
50000/200000 = 0.25 → a quarter of one core
Container vs VM in one rule
one kernel = container; a whole extra kernel = VM