Two halves make a container, and they are worth separating. The packaging half is an image: a stack of read-only filesystem layers, built from a recipe file, holding your code alongside the exact library versions it was tested against. The isolating half comes from the Linux kernel rather than from virtualisation. Namespaces give the process its own view of the filesystem, the process table and the network, while control groups cap how much processor time and memory it may take. Nothing boots. No guest operating system exists inside the package, which is why starting one costs roughly what starting a process costs, whereas a VPS needs the time a computer needs to switch itself on. The price of that speed is a shared kernel, so the partition between two containers is thinner than a hypervisor's and a kernel vulnerability is everyone's problem simultaneously. Docker made the format ordinary, then handed the specifications to the Open Container Initiative, which is why an image built with Docker also runs under Podman, under containerd and on a Kubernetes node without anybody renegotiating a format.
- The environment stops being a variable. Works on my machine was never a lie about the code; it was a difference in what surrounded the code. Freezing the surroundings into the artefact removes the argument.
- One build, promoted everywhere. The identical image that passed tests is the image that reaches production, rather than a fresh install performed separately on each server and hoped to match.
- State needs a decision. A container's own filesystem is disposable, so uploads, databases and anything else that must survive a restart belong in a mounted volume or an external service. Discovering this after a redeploy is a rite of passage nobody enjoys.
- Images age. A base layer pulled last spring carries last spring's unpatched system libraries, so rebuilding and scanning them is continuous maintenance, not a task anybody finishes.
A single container running on one machine is simply a tidier deployment. Forty containers spread over a dozen machines is a distributed system, and that is where Kubernetes arrives. It schedules workloads onto nodes, restarts whatever dies, rolls new versions out gradually, and rolls them back when the health checks disagree with the optimism of the deploy. It also brings a vocabulary of its own, failure modes of its own, and in practice a person whose working week is partly devoted to it. The useful question for a small team is not whether the thing is good, because it plainly is, but whether the labour it automates is labour anybody is currently performing. A single application behind a load balancer, shipped with Compose or a managed container service from your provider, covers a great deal of territory before a cluster starts earning its keep. The industry consensus that arrived with the technology, that everything must be orchestrated, has quietly softened into something closer to it depends on how many moving parts you have.
