Run docker run alpine /bin/sh and you land in what looks like a brand-new machine. Its own filesystem. Its own network interface. Its own process list, where your shell is PID 1. Its own memory limit. It feels like a very small virtual machine.
It isn't. There is no hypervisor here, and no second kernel. A container is an ordinary Linux process that has been lied to about the world around it — and this course is about who tells the lies, and how.
Start a container and look at it from the host:
This one is a recording — the commands are real, but nothing is running here. Type them into your own shell to follow along.
The same process. One kernel, one process table, one scheduler. From the host it is PID 30412 among hundreds; from the inside it is PID 1 and nearly alone.
A virtual machine could not do this. A VM runs its own kernel on emulated hardware, and its processes are invisible to the host because they are genuinely somewhere else. Here nothing is emulated and nothing is hidden — the container's process is simply being shown a filtered view of the machine it is already running on.
docker exec into a container and run uname -r. Whose kernel version do you see?
Strip away the tooling and a container is the intersection of four things:
/, so it sees its own libraries and binaries rather than yours.Every one of those is a plain kernel feature with a name, a command-line tool, and a manual page. None of them was invented by Docker; most predate it by years. Docker's contribution was packaging, distribution, and an ergonomic front end — which is a genuinely large contribution, and also not the same thing as the isolation itself.
Over the next eight lessons we assemble a container from those primitives, with no container runtime installed at any point. No Docker, no containerd, no runc, no Podman.
The layers, in the order we build them:
unsharechroot, to make the snapshot the container's /Then one command that composes all six into a single process, and a cleanup lesson that takes it apart again.
The point is not that you should build containers this way. The point is that when a production container cannot resolve DNS, or gets OOM-killed at a limit nobody set, or sees a volume mount that behaves strangely, you will know which of these six layers to look at — instead of restarting the pod and hoping.
The walkthrough follows NH66's write-up of their FOSS Meet '26 container workshop, What Is a Container, Really?, which is the source for the exact command sequence used here.
A Linux machine you have root on, and are willing to make a mess of. A VM or a cloud box is ideal; none of this belongs on a laptop you need working an hour from now.
The tools come from three packages:
sudo apt update
sudo apt install -y btrfs-progs iproute2 iptables cgroup-tools util-linux
util-linux supplies unshare and nsenter and is almost certainly installed already. Everything else is small.
You also need to know that this course assumes the ground covered in Linux Basics and Shell Scripting — the filesystem, processes, permissions, and enough shell to read a five-line command. Nothing beyond that.
Which of these is *not* one of the kernel mechanisms a container is built from?
Next up: namespaces — the mechanism that decides what a process is allowed to see.
