Docker Internals — Namespaces, cgroups & OverlayFS
AdvancedDocker containers are not magic — they are Linux processes with namespace isolation, cgroup resource limits, and an OverlayFS layered filesystem. Understanding internals helps you debug, optimise, and reason about security.
Overview
Docker does not create a new OS or a new kernel. It creates an ordinary Linux process and applies three kernel features to isolate it: (1) Namespaces: separate the process's view of the system (PID namespace: container thinks it is PID 1; net namespace: own network stack; mnt namespace: own filesystem; uts: own hostname; user: own UID mapping; ipc: own IPC). (2) cgroups (control groups): limit CPU, memory, I/O, and network bandwidth for the process group. (3) OverlayFS: a Union File System that stacks image layers as the container's root filesystem with a writable layer on top.
Namespaces — Process View Isolation
Each namespace type gives a container its own isolated view of a system resource. The container process thinks it is alone on the machine.
# See a container's namespaces from the host
docker run -d --name demo nginx:alpine
PID=$(docker inspect -f '{{.State.Pid}}' demo)
# List namespaces of the container's root process
ls -la /proc/$PID/ns/
# lrwxrwxrwx ... cgroup -> cgroup:[4026531835]
# lrwxrwxrwx ... ipc -> ipc:[4026532350] ↠isolated IPC
# lrwxrwxrwx ... mnt -> mnt:[4026532348] ↠isolated filesystem
# lrwxrwxrwx ... net -> net:[4026532352] ↠isolated network stack
# lrwxrwxrwx ... pid -> pid:[4026532349] ↠isolated PIDs (PID 1 inside)
# lrwxrwxrwx ... uts -> uts:[4026532347] ↠isolated hostname
# lrwxrwxrwx ... user -> user:[4026531837] ↠UID/GID mapping
# Inside container, nginx is PID 1:
docker exec demo ps aux
# PID USER COMMAND
# 1 root nginx: master process
# 31 nginx nginx: worker process
# On host, it is just another PID (e.g., 18423):
ps aux | grep nginxcgroups — Resource Limits
cgroups (control groups) limit and account for resource usage. Docker maps --memory, --cpus, and other flags to cgroup configurations.
# Run container with resource limits
docker run -d \
--memory=512m \ # max 512 MB RAM
--memory-swap=512m \ # = memory: no swap allowed
--cpus=1.5 \ # max 1.5 CPU cores
--cpu-shares=512 \ # relative weight (default 1024) when CPU is contested
--pids-limit=100 \ # max 100 processes (prevents fork bombs)
--name limited-app \
my-app:latest
# View cgroup limits on host (cgroups v2)
cat /sys/fs/cgroup/system.slice/docker-$(docker inspect -f '{{.Id}}' limited-app).scope/memory.max
# 536870912 ↠512 MB in bytes
# Check actual usage
docker stats limited-app
# CONTAINER CPU% MEM USAGE / LIMIT MEM%
# limited-app 0.1% 45MiB / 512MiB 8.8%
# OOM (Out of Memory) Kill — what happens when limit exceeded:
# Docker kills the container (exit code 137)
# docker events | grep oom ↠see OOM kill eventsOverlayFS — How Image Layers Work at the Kernel Level
OverlayFS is a Union File System that merges directories (layers) into a single coherent view. Docker uses it to stack image layers as "lowerdir" and add a writable "upperdir" per container.
# OverlayFS structure on the host
ls /var/lib/docker/overlay2/
# Each directory is a layer (identified by chain ID)
# <layer-id>/
# diff/ ↠the actual filesystem files for this layer
# link ↠short name for the layer
# lower ↠pointer to parent layer
# merged/ ↠the unified view (container's root filesystem)
# work/ ↠OverlayFS working directory
# OverlayFS mount (conceptual):
# mount -t overlay overlay \
# -o lowerdir=layer3:layer2:layer1, ↠image layers (read-only)
# upperdir=container-writable, ↠writable layer (this container only)
# workdir=overlay-work \
# /var/lib/docker/overlay2/.../merged ↠container's root /
# Copy-on-Write:
# 1. Container reads /etc/nginx/nginx.conf → found in lowerdir layer2 → returns it
# 2. Container writes to /etc/nginx/nginx.conf
# → file is COPIED to upperdir first
# → write goes to the copy in upperdir
# → lower layer unchanged (other containers unaffected)
# Inspect overlay mounts:
docker inspect demo | grep -A 20 '"GraphDriver"'Key Points to Remember
- 1Docker containers are Linux processes with namespace isolation — not VMs.
- 2PID namespace: container thinks its process is PID 1 (not the host's PID).
- 3cgroups enforce hard limits on CPU, memory, and processes — exceeding memory limit triggers OOM kill.
- 4OverlayFS stacks read-only image layers + writable container layer using Copy-on-Write.
- 5Writing a file in a container copies it from the lower layer to the writable upper layer (doesn't modify the image).
- 6A "fat" image with many files is slow to start because more data must be read across layers.
Interview Questions
Sign in to ask AriaHow does Docker achieve container isolation without a full OS?
What is Copy-on-Write in the context of OverlayFS?
Ask Aria about Docker Internals — Namespaces, cgroups & OverlayFS
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.