Container internals: namespaces, cgroups and chroot
Without a container engine, you build your own container step by step from the kernel's isolation building blocks and see what each layer protects and what it doesn't.
Level 401 · 15 lessons · 12 practice labs
Lessons
Building blocks
- chroot: the first isolation and its limits
- Namespaces: pid, mount, uts, ipc, net and user
- Experimenting with unshare and nsenter
- User namespaces: root inside, an ordinary user outside
- Short task: inspect a running container's namespaces from outside
Your own container
- The root file system and pivot_root
- Layers with overlayfs
- Giving a container cgroup limits
- Dropping capabilities and seccomp
- Short task: build a container by hand and open a shell inside
Tools
- Lightweight containers with systemd-nspawn
- The OCI runtime: runc and config.json
- Why isolation breaks: lessons from past incidents
- Short task: isolate an old service inside nspawn
Wrap-up
- Capstone: write a tiny container runner in half a page of script and report its limits
Practice labs
- List a process's namespaces: Find which namespaces of a container process differ from the host and submit how many differ.
- Create an isolated PID and mount space with unshare: Start a shell in new PID and mount namespaces and show only its own processes are visible and mounts do not leak to the host.
- Debug a tool-less container from the host with nsenter: Enter the network and mount namespaces of a container with no tools inside from the host and find the listening port and the wrong mount.
- Build a layered file system with overlayfs: Mount a read-only lower and writable upper layer and show changes stay in the upper layer only.
- Start a process that switches to its own root file system: Prepare a small root file system and switch into it in new namespaces, verifying host files are not visible.
- Build a limited, networked container by hand: Assemble a container by hand from namespaces, a cgroup memory limit, an overlay root and a veth pair, proving lab network access and the limit.
- Read the ID mapping of a user namespace: Read the ID map files of an unprivileged container process and write down the host ID of root inside.
- Reduce a container's capabilities to what it needs: Decode a container process's capability set, restart it with the unneeded ones dropped and show the application works.
- Derive and apply a seccomp profile for a container: Trace the system calls an application uses to derive an allow list, apply the profile and show a blocked call in the audit record.
- Run a minimal container with runc: Start a container through runc with a root file system and generated config file and list its state.
- Collect a running container's kernel-level traces: From the host find a container's cgroup path, namespace IDs, overlay layer directories and veth peer.
- Audit container isolation layer by layer: Audit namespace sharing, capabilities, seccomp and mounts of three given containers and report the weakly isolated one with reasons.
About this course
Without a container engine, you build your own container step by step from the kernel's isolation building blocks and see what each layer protects and what it doesn't.
What you will learn
- Building blocks
- Your own container
- Tools
- Wrap-up
Prerequisites
You should have practised the topics of the same path up to level 301.
Lab environment
Lessons run in your own Kali Linux terminal that opens in the browser. Nothing to install; the lab starts clean in every lesson.
Frequently asked questions
- Is this course right for my level?
- The course is at level 401; it assumes you know the topics of the lower-level courses.
- Is there anything to install?
- No. Every lesson runs in your own lab environment that opens in the browser.
- How do lessons work?
- Each lesson has 8 to 10 steps and a short quiz. Early steps show the command to type, later steps give less help; if two attempts fail, the solution opens.
- Can I try it for free?
- Yes. The first three lessons of every course are free.