Concept · Running systems
Namespaces and cgroups
A container is a normal Linux process with a restricted view (namespaces) and a budget (cgroups).
A container isn't a small virtual machine. It's an ordinary Linux process that the kernel shows a restricted view of the system and puts on a resource budget. Two kernel features do most of the work.
Namespaces: what the process can see
Each namespace type gives the process its own private copy of one kind of system resource:
| Namespace | Isolates |
|---|---|
pid | Process IDs: the container sees itself as PID 1 and can't see host processes |
mnt | Mount points: its own root filesystem (the image) |
net | Network interfaces, IPs, ports, routing tables |
uts | Hostname |
ipc | Shared memory and message queues |
user | User IDs: root inside can map to an unprivileged user outside |
cgroup | Its view of the cgroup tree |
docker run --rm alpine ps # shows only the container's processescgroups: what the process can use
Control groups limit and account for CPU, memory, I/O and number of processes:
resources:
requests: { cpu: 250m, memory: 256Mi } # scheduling guarantee
limits: { cpu: "1", memory: 512Mi } # hard ceiling- Over the memory limit, the process is OOM-killed.
- Over the CPU limit, it's throttled, which shows up as latency spikes, not errors.
- A
pidslimit stops a fork bomb from taking down the node.
Language runtimes have to read these limits. Go reads cgroup CPU limits for GOMAXPROCS from Go 1.25, and GOMEMLIMIT should be set a little below the memory limit.
The security boundary is thinner than a VM's
All containers on a host share one kernel. A kernel vulnerability, or a container given too much privilege, can lead to an escape onto the host. The defaults are reasonable, and most hardening is about not undoing them:
- Don't run as root. Set
USERin the image andrunAsNonRoot: true. Use user namespaces where available. - Drop Linux capabilities (
drop: [ALL]) and add back only what's needed. - Never use
--privilegedor mount the Docker socket or host paths into an application container. Either one is effectively root on the host. - Keep seccomp and AppArmor/SELinux profiles on, with
RuntimeDefaultat minimum, and use a read-only root filesystem. - For untrusted code, add a stronger boundary: gVisor, Kata Containers or Firecracker microVMs.
All of this is least privilege applied to a process. The container security lesson adds image scanning and minimal base images.