Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Containers package an application together with its dependencies into a single artifact that runs the same on your laptop, a CI runner, and a production node. Unlike VMs, containers share the host kernel and start in milliseconds, which is why a modern fleet can pack hundreds of workloads onto a single box. Understanding the isolation model — namespaces, cgroups, and a layered filesystem — is the difference between treating Docker as magic and reasoning about it as a tool.
Compare a VM-shaped workload to a container-shaped workload by inspecting what the host actually sees.
docker run -d --name web nginx:1.27-alpine and confirm the container PID on the host matches a real nginx process via ps.--memory=64m on a container running stress-ng --vm 1 --vm-bytes 200M and observe the OOM kill in docker logs.time docker run --rm alpine:3.20 echo hi against booting an EC2 t3.micro and SSHing in — note the order-of-magnitude difference.Use these three in order. Each builds on the one before.
In one paragraph, explain what a Linux container is and how it differs from a virtual machine, like I'm new to it.
Walk me through how Linux namespaces and cgroups together create the illusion of an isolated environment for a containerized process, step by step.
Given a workload that needs to load a custom kernel module, explain why a container is the wrong tool and what isolation primitive (VM, microVM, or other) you would reach for instead and why.
# A VM boots a full kernel; a container shares the host kernel.
# Look at processes the container exposes to the host:
docker run -d --name web nginx:1.27-alpine
docker inspect -f '{{.State.Pid}}' web
# That PID exists on the host:
ps -p $(docker inspect -f '{{.State.Pid}}' web) -o pid,comm
# But inside the container, PID 1 is nginx:
docker exec web ps -ef
# Namespaces give the container its own view:
sudo ls -la /proc/$(docker inspect -f '{{.State.Pid}}' web)/ns
# cgroups bound the resources it can use:
docker run --rm --memory=128m --cpus=0.5 alpine:3.20 sh -c 'cat /sys/fs/cgroup/memory.max'