Keyboard Shortcuts N Next post
P Previous post
S Save / unsave
R Read aloud
T Toggle theme
/ Focus search
Esc Close panels
🔥
Ready to read...
Docker Docker & Containers: From Zero to Production Docker Basics intermediate Linux Module 1 — Container Fundamentals

How Containers Work Under the Hood — Namespaces and Cgroups

Reviewed & accurate
AI Summary

What You'll Learn

Intermediate

  • The three Linux kernel features that make containers possible
  • How namespaces provide isolation
  • How cgroups provide resource limits
  • How union filesystems enable image layers
The big picture
Docker didn't invent containers — it made them easy to use. The underlying technology has been in the Linux kernel since 2007 (cgroups) and 2002 (namespaces). Docker's innovation was packaging these features into a developer-friendly tool.

The Three Pillars of Containers

FeatureWhat it doesWithout it
NamespacesIsolation — what the container can seeContainer sees all processes, networks, files on the host
CgroupsResource limits — what the container can useContainer can consume all CPU, RAM, disk on the host
Union filesystemLayered storage — how images are builtEach container needs a full copy of the filesystem

1. Namespaces — Isolation

Namespaces are a Linux kernel feature that partitions kernel resources. Each container gets its own set of namespaces, so it sees a isolated view of the system.

The six main namespace types

NamespaceIsolatesExample
PIDProcess IDsContainer sees itself as PID 1, not the host's PID
NETNetwork interfaces, ports, routesContainer has its own IP, loopback, routing table
MNTMount points (filesystem view)Container has its own root filesystem
UTSHostnameContainer has its own hostname
IPCInter-process communicationContainer's shared memory is isolated
USERUser and group IDsContainer's root (UID 0) maps to non-root on host

Visual: PID namespace

PID Namespace Isolation Host View PID 1: systemd (init) PID 1500: dockerd PID 3000: container process Container View PID 1: my-app (looks like init!) (cannot see host processes) (isolated from host PID tree)
The same process appears as PID 3000 on the host but PID 1 inside the container
Source
Namespace behavior is defined by the Linux kernel. See namespaces(7) man page for the authoritative reference.

2. Cgroups — Resource Limits

Control groups (cgroups) limit and account for the resources a process (or container) can use. Without cgroups, a single container could consume all CPU and RAM, starving everything else on the host.

What cgroups can limit

ResourceDocker flagExample
CPU shares--cpu-sharesGive container 2x CPU priority
CPU cores--cpusLimit to 1.5 cores
Memory--memory / -mLimit to 512 MB RAM
Swap--memory-swapLimit swap usage
Block I/O--device-read-bpsLimit disk read speed
PIDs--pids-limitPrevent fork bombs

Example: limit a container to 512 MB and 1 CPU

Terminalbash
docker run --memory=512m --cpus=1 ubuntu sleep 3600

If the container tries to use more than 512 MB, the kernel's OOM (Out Of Memory) killer terminates the process. This protects the host.

Why this matters in production
Without resource limits, a single misbehaving container can crash the entire host. In Kubernetes, every container must have CPU and memory limits. Docker makes it easy to set them per container.

3. Union Filesystem — Image Layers

A Docker image is not a single file — it's a stack of read-only layers, each representing one instruction in the Dockerfile. The union filesystem (UnionFS) combines these layers into a single coherent filesystem view.

Writable Container Layer (ephemeral — deleted when container stops) Layer 4: COPY . /app (your code) 12 MB Layer 3: RUN npm install (dependencies) 145 MB Layer 2: RUN apt-get install curl 8 MB Layer 1: FROM ubuntu:22.04 (base image) (read-only, shared across all containers using it) 77 MB ↑ R/W Read-Only ↓ Key insight: Each instruction in your Dockerfile creates a new read-only layer. When you run a container, Docker adds a writable layer on top.
Docker image layers — read-only stack with a writable top layer per container

How the union filesystem works

Layer 1 (base): FROM ubuntu:22.04 — pulls the Ubuntu base image (77 MB).
Layer 2: RUN apt-get install curl — adds curl (8 MB). Only the diff is stored.
Layer 3: RUN npm install — adds dependencies (145 MB).
Layer 4: COPY . /app — adds your code (12 MB).
Writable layer: When you run docker run, Docker adds a thin writable layer on top. Any changes the container makes go here — and are lost when the container stops.

Why layers matter

  • Sharing: Two containers using ubuntu:22.04 share the same base layer — no duplication.
  • Caching: If a layer hasn't changed, Docker reuses it during builds — faster builds.
  • Efficiency: Only changed layers are pushed/pulled, not the entire image.
Supported union filesystems
Docker supports multiple storage drivers: overlay2 (default and recommended), aufs (legacy), devicemapper, btrfs, zfs. overlay2 is the modern default on most Linux distributions.

Putting It All Together

What Makes a Container Namespaces Isolation PID, NET, MNT, UTS "What can I see?" Cgroups Resource limits CPU, RAM, I/O, PIDs "How much can I use?" UnionFS Layered storage Image layers "How is data stored?" = A Docker Container Isolated process with resource limits and layered filesystem
A Docker container = namespaces + cgroups + union filesystem

Common Mistakes

Avoid these
  • Thinking Docker invented containers. Linux had namespaces and cgroups for years before Docker. Docker made them usable.
  • Assuming containers are as secure as VMs. They're not. A kernel exploit can escape a container. Use VMs for untrusted workloads.
  • Forgetting that containers share the host kernel. A Linux container cannot run on a Windows host (without a Linux VM). The kernel must match.
  • Not setting resource limits. Without cgroup limits, one container can starve the host. Always set --memory and --cpus in production.

Practical Exercise (5 minutes)

Run docker run -it ubuntu bash
Inside the container, run ps aux — notice you only see processes inside the container, not the host
Run hostname — it's a different hostname than your host
Run cat /proc/1/cgroup — see the cgroup path
Exit the container (exit)

Mini Challenge

Run two containers with different resource limits and see the difference:

Terminalbash
# Container A: limited to 256MB
docker run -it --memory=256m ubuntu bash

# In another terminal, Container B: unlimited
docker run -it ubuntu bash

# In each, try: yes > /dev/null
# (press Ctrl+C after a few seconds)
# Notice A is throttled, B uses all CPU

Key Takeaways

  • Containers are built on three Linux kernel features: namespaces, cgroups, and union filesystems.
  • Namespaces isolate what the container can see (processes, network, files).
  • Cgroups limit what the container can use (CPU, RAM, I/O).
  • UnionFS stacks read-only layers into a single filesystem view.
  • Docker didn't invent these — it made them easy to use.
  • Containers share the host kernel — they're not as isolated as VMs.
Previously: Lesson 02 compared containers to VMs.
Today: You went under the hood: namespaces, cgroups, and union filesystems.
Next: Lesson 04 covers the Docker architecture: client, daemon, and registry.

FAQ

Do I need to understand namespaces and cgroups to use Docker?

No. Docker abstracts them away. You can use Docker effectively without knowing the kernel internals. But understanding them helps you debug problems, set resource limits correctly, and understand why containers behave the way they do.

Can I create a container without Docker?

Yes. You can use unshare and cgcreate commands directly. But it's painful — Docker handles all the plumbing for you. Tools like podman and runc also create containers using the same kernel features.

Test Your Knowledge
How did you find this?

Comments

Join the discussion! Sign in with your Google or Blogger account, or comment as Anonymous - no account needed. For quick questions, also reach me on Telegram @cytestch.

Comments