[{"data":1,"prerenderedAt":380},["ShallowReactive",2],{"mdc-rkso3j-key":3,"mdc--dpgkei-key":38,"mdc--wslsrh-key":54,"mdc--3mneba-key":73,"mdc-539c2b-key":85,"mdc--w2vvnt-key":158,"mdc-ss4n9o-key":289,"mdc--iy52tp-key":365},{"data":4,"body":5},{},{"type":6,"children":7},"root",[8,25],{"type":9,"tag":10,"props":11,"children":12},"element","p",{},[13,16,23],{"type":14,"value":15},"text","Run ",{"type":9,"tag":17,"props":18,"children":20},"code",{"className":19},[],[21],{"type":14,"value":22},"docker run alpine /bin/sh",{"type":14,"value":24}," 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.",{"type":9,"tag":10,"props":26,"children":27},{},[28,30,36],{"type":14,"value":29},"It isn't. There is no hypervisor here, and no second kernel. ",{"type":9,"tag":31,"props":32,"children":33},"strong",{},[34],{"type":14,"value":35},"A container is an ordinary Linux process that has been lied to about the world around it",{"type":14,"value":37}," — and this course is about who tells the lies, and how.",{"data":39,"body":40},{},{"type":6,"children":41},[42,49],{"type":9,"tag":43,"props":44,"children":46},"h2",{"id":45},"the-evidence-that-it-isnt-a-vm",[47],{"type":14,"value":48},"The evidence that it isn't a VM",{"type":9,"tag":10,"props":50,"children":51},{},[52],{"type":14,"value":53},"Start a container and look at it from the host:",{"data":55,"body":56},{},{"type":6,"children":57},[58,63,68],{"type":9,"tag":59,"props":60,"children":62},"terminal-teaser",{":lines":61},"[{\"cmd\":\"docker run -d --name demo alpine sleep 300\",\"out\":\"8f3c1a...\"},{\"cmd\":\"ps -eo pid,comm | grep sleep\",\"out\":\"30412 sleep\"},{\"cmd\":\"docker exec demo ps -eo pid,comm\",\"out\":\"PID   COMMAND\\n    1 sleep\\n    7 ps\"}]",[],{"type":9,"tag":10,"props":64,"children":65},{},[66],{"type":14,"value":67},"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.",{"type":9,"tag":10,"props":69,"children":70},{},[71],{"type":14,"value":72},"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.",{"data":74,"body":75},{},{"type":6,"children":76},[77],{"type":9,"tag":78,"props":79,"children":84},"quiz",{":answer":80,":options":81,"explanation":82,"question":83},"0","[\"The host's — a container shares the host kernel and has none of its own\",\"The container image's, which ships a kernel\",\"A virtualised version reported by the container runtime\"]","There is exactly one kernel involved. This is why a Linux container cannot run on a Windows or macOS kernel without a Linux VM underneath, and why a container needing a specific kernel feature depends on the *host* having it, not the image.","`docker exec` into a container and run `uname -r`. Whose kernel version do you see?",[],{"data":86,"body":87},{},{"type":6,"children":88},[89,95,100,153],{"type":9,"tag":43,"props":90,"children":92},{"id":91},"four-ideas-and-docker-is-the-bow-on-top",[93],{"type":14,"value":94},"Four ideas, and Docker is the bow on top",{"type":9,"tag":10,"props":96,"children":97},{},[98],{"type":14,"value":99},"Strip away the tooling and a container is the intersection of four things:",{"type":9,"tag":101,"props":102,"children":103},"ol",{},[104,123,133,143],{"type":9,"tag":105,"props":106,"children":107},"li",{},[108,113,115,121],{"type":9,"tag":31,"props":109,"children":110},{},[111],{"type":14,"value":112},"An isolated filesystem",{"type":14,"value":114}," — its own ",{"type":9,"tag":17,"props":116,"children":118},{"className":117},[],[119],{"type":14,"value":120},"/",{"type":14,"value":122},", so it sees its own libraries and binaries rather than yours.",{"type":9,"tag":105,"props":124,"children":125},{},[126,131],{"type":9,"tag":31,"props":127,"children":128},{},[129],{"type":14,"value":130},"An isolated network",{"type":14,"value":132}," — its own interfaces and routing table, so it can bind port 80 without fighting you for it.",{"type":9,"tag":105,"props":134,"children":135},{},[136,141],{"type":9,"tag":31,"props":137,"children":138},{},[139],{"type":14,"value":140},"Capped resources",{"type":14,"value":142}," — a ceiling on CPU and memory, so it cannot starve the host.",{"type":9,"tag":105,"props":144,"children":145},{},[146,151],{"type":9,"tag":31,"props":147,"children":148},{},[149],{"type":14,"value":150},"An isolated process tree",{"type":14,"value":152}," — its own PID space, so it cannot see or signal your processes.",{"type":9,"tag":10,"props":154,"children":155},{},[156],{"type":14,"value":157},"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.",{"data":159,"body":160},{},{"type":6,"children":161},[162],{"type":9,"tag":163,"props":164,"children":166},"deep-dive",{"title":165},"What we are building, and why by hand",[167,172,177,259,264,269],{"type":9,"tag":10,"props":168,"children":169},{},[170],{"type":14,"value":171},"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.",{"type":9,"tag":10,"props":173,"children":174},{},[175],{"type":14,"value":176},"The layers, in the order we build them:",{"type":9,"tag":178,"props":179,"children":180},"ul",{},[181,193,209,228,239,249],{"type":9,"tag":105,"props":182,"children":183},{},[184,186,191],{"type":14,"value":185},"a ",{"type":9,"tag":31,"props":187,"children":188},{},[189],{"type":14,"value":190},"copy-on-write root filesystem",{"type":14,"value":192}," with btrfs snapshots, so containers share a base image without being able to damage it",{"type":9,"tag":105,"props":194,"children":195},{},[196,201,203],{"type":9,"tag":31,"props":197,"children":198},{},[199],{"type":14,"value":200},"namespaces",{"type":14,"value":202}," — PID, mount, UTS, IPC — via ",{"type":9,"tag":17,"props":204,"children":206},{"className":205},[],[207],{"type":14,"value":208},"unshare",{"type":9,"tag":105,"props":210,"children":211},{},[212,221,223],{"type":9,"tag":31,"props":213,"children":214},{},[215],{"type":9,"tag":17,"props":216,"children":218},{"className":217},[],[219],{"type":14,"value":220},"chroot",{"type":14,"value":222},", to make the snapshot the container's ",{"type":9,"tag":17,"props":224,"children":226},{"className":225},[],[227],{"type":14,"value":120},{"type":9,"tag":105,"props":229,"children":230},{},[231,232,237],{"type":14,"value":185},{"type":9,"tag":31,"props":233,"children":234},{},[235],{"type":14,"value":236},"veth pair and bridge",{"type":14,"value":238},", giving it a private wire to the host",{"type":9,"tag":105,"props":240,"children":241},{},[242,247],{"type":9,"tag":31,"props":243,"children":244},{},[245],{"type":14,"value":246},"iptables NAT",{"type":14,"value":248},", so that private wire reaches the internet",{"type":9,"tag":105,"props":250,"children":251},{},[252,257],{"type":9,"tag":31,"props":253,"children":254},{},[255],{"type":14,"value":256},"cgroups",{"type":14,"value":258},", capping CPU and memory",{"type":9,"tag":10,"props":260,"children":261},{},[262],{"type":14,"value":263},"Then one command that composes all six into a single process, and a cleanup lesson that takes it apart again.",{"type":9,"tag":10,"props":265,"children":266},{},[267],{"type":14,"value":268},"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.",{"type":9,"tag":10,"props":270,"children":271},{},[272,274,287],{"type":14,"value":273},"The walkthrough follows NH66's write-up of their FOSS Meet '26 container workshop, ",{"type":9,"tag":275,"props":276,"children":280},"a",{"href":277,"rel":278},"https://nh66.ai/blog/what-is-a-container-really-building-one-from-scratch-with-linux-primitives/",[279],"nofollow",[281],{"type":9,"tag":282,"props":283,"children":284},"em",{},[285],{"type":14,"value":286},"What Is a Container, Really?",{"type":14,"value":288},", which is the source for the exact command sequence used here.",{"data":290,"body":291},{},{"type":6,"children":292},[293,299,304,309,321,347],{"type":9,"tag":43,"props":294,"children":296},{"id":295},"what-you-need-to-follow-along",[297],{"type":14,"value":298},"What you need to follow along",{"type":9,"tag":10,"props":300,"children":301},{},[302],{"type":14,"value":303},"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.",{"type":9,"tag":10,"props":305,"children":306},{},[307],{"type":14,"value":308},"The tools come from three packages:",{"type":9,"tag":310,"props":311,"children":315},"pre",{"className":312,"code":314,"language":14},[313],"language-text","sudo apt update\nsudo apt install -y btrfs-progs iproute2 iptables cgroup-tools util-linux\n",[316],{"type":9,"tag":17,"props":317,"children":319},{"__ignoreMap":318},"",[320],{"type":14,"value":314},{"type":9,"tag":10,"props":322,"children":323},{},[324,330,332,337,339,345],{"type":9,"tag":17,"props":325,"children":327},{"className":326},[],[328],{"type":14,"value":329},"util-linux",{"type":14,"value":331}," supplies ",{"type":9,"tag":17,"props":333,"children":335},{"className":334},[],[336],{"type":14,"value":208},{"type":14,"value":338}," and ",{"type":9,"tag":17,"props":340,"children":342},{"className":341},[],[343],{"type":14,"value":344},"nsenter",{"type":14,"value":346}," and is almost certainly installed already. Everything else is small.",{"type":9,"tag":10,"props":348,"children":349},{},[350,352,357,358,363],{"type":14,"value":351},"You also need to know that this course assumes the ground covered in ",{"type":9,"tag":282,"props":353,"children":354},{},[355],{"type":14,"value":356},"Linux Basics",{"type":14,"value":338},{"type":9,"tag":282,"props":359,"children":360},{},[361],{"type":14,"value":362},"Shell Scripting",{"type":14,"value":364}," — the filesystem, processes, permissions, and enough shell to read a five-line command. Nothing beyond that.",{"data":366,"body":367},{},{"type":6,"children":368},[369,375],{"type":9,"tag":78,"props":370,"children":374},{":answer":80,":options":371,"explanation":372,"question":373},"[\"A hypervisor that virtualises the CPU for the container\",\"Namespaces, which limit what a process can see\",\"cgroups, which limit what a process can consume\"]","Hypervisors belong to virtual machines. Containers use no CPU virtualisation at all — the process runs directly on the host CPU, at native speed, scheduled by the host kernel like everything else. That is the whole performance argument for containers.","Which of these is *not* one of the kernel mechanisms a container is built from?",[],{"type":9,"tag":10,"props":376,"children":377},{},[378],{"type":14,"value":379},"Next up: namespaces — the mechanism that decides what a process is allowed to see.",1787908868344]