Docker kills the oldest excuse in software: "it works on my machine." It packages an application together with everything it needs to run — the code, the runtime, the libraries, the settings — into one portable container that behaves identically on a laptop, a colleague's machine, a test server, and production. It's lightweight (it shares the host's kernel, unlike a virtual machine), fast to start, and built on open standards. This is what a container actually is, how the workflow works, where it fits next to Kubernetes and managed clouds, and when it's the wrong tool.
Software almost never runs in isolation. An app needs a specific language version, particular libraries, environment variables, system packages, and a dozen other assumptions about the machine it sits on. When any of those differ between your laptop and the server, things break — the legendary "works on my machine" failure. A container solves this by bundling the app and all of those dependencies into a single, self-contained unit that carries its world with it.
Docker, released in 2013, is the tool that made containers mainstream. The core insight isn't new — Linux had the underlying primitives (namespaces for isolation, cgroups for resource limits) for years — but Docker wrapped them in a workflow so simple that containers went from a kernel-hacker curiosity to the default way modern software is packaged and shipped.
The crucial distinction from a virtual machine: a container shares the host's operating-system kernel rather than booting a whole second OS. That makes it dramatically lighter — megabytes not gigabytes, starting in milliseconds not minutes — while still keeping each app isolated from the others. You can run dozens of containers on one modest server where you'd fit only a handful of VMs.
Docker is shipping containers for software: a standard box you pack your application into once, that any compatible machine — anywhere — can pick up and run exactly as you built it. The standardisation is the whole value: the box is the same shape no matter what's inside or where it lands.
An image is the blueprint — a read-only, layered snapshot of your app and its dependencies. A container is a running instance of an image. A registry (like Docker Hub) is where images are stored and shared. You write a Dockerfile describing how to build the image, and three commands cover most of daily life.
A Dockerfile is a plain recipe. Each line is a step, and each step becomes a cached layer — so rebuilds only redo what changed:
# Start from a small official base image FROM node:22-alpine WORKDIR /app # Install dependencies first (cached unless package.json changes) COPY package*.json ./ RUN npm ci --omit=dev # Then copy the rest of the source COPY . . EXPOSE 3000 CMD ["node", "server.js"]
Build it into an image, run it as a container, push it to a registry so others (or a server) can pull it:
# Build an image and tag it docker build -t myapp:1.0 . # Run a container, mapping a host port to the container port docker run -p 3000:3000 myapp:1.0 # Share it via a registry docker push registry.example.com/myapp:1.0
Real apps are rarely one container — you've got a web app, a database, maybe a cache. Docker Compose describes the whole set in one compose.yaml and brings it all up with a single command:
# compose.yaml — the whole stack, one file services: web: build: . ports: ["3000:3000"] depends_on: [db] db: image: postgres:17 environment: POSTGRES_PASSWORD: secret # bring the whole stack up: docker compose up
Because each Dockerfile step is a cached layer, changing one line of source code doesn't reinstall every dependency — only the layers after the change rebuild. Order your Dockerfile from least-changing (base image, dependencies) to most-changing (your source) and builds drop from minutes to seconds. Getting that ordering right is the single highest-leverage Docker skill.
Virtual machines and containers both isolate workloads — but a VM virtualises the hardware and boots a full OS, while a container virtualises the operating system and shares the host kernel. That difference drives everything: size, speed, density, and the isolation trade-off.
| Dimension | Container (Docker) | Virtual machine |
|---|---|---|
| What's virtualised | The OS — shares the host kernel | The hardware — full guest OS each |
| Size | Megabytes | Gigabytes |
| Start time | Milliseconds to seconds | Tens of seconds to minutes |
| Density | Dozens per host | A handful per host |
| Isolation | Strong, but shares the kernel | Strongest — full hardware boundary |
| Best for | Packaging & shipping apps, microservices, CI | Running different OSes, hard multi-tenant isolation |
In practice you usually run containers inside VMs. A cloud gives you a VM (the strong hardware-level boundary, often for multi-tenant security); you run many containers on it (the packaging and density win). "Containers vs VMs" is rarely a real either/or — the question is how many of each, and where the isolation boundary needs to be.
"Docker" is a company, a CLI, a daemon, a desktop app, and a registry — and underneath it all is an open standard (OCI) that means images and runtimes aren't locked to Docker the vendor. Knowing which piece is which keeps you out of the licensing and lock-in traps.
The core runtime + CLI that builds and runs containers. Apache-2.0 licensed, free, Linux-native. The part that actually does the work.
The Mac/Windows app that runs Engine in a tidy VM with a UI. Free for personal / small use; a paid subscription for larger organisations.
The default public registry of images. Official bases (node, postgres, nginx) live here. Private registries (GHCR, ECR, Artifact Registry) are common too.
Compose runs a multi-service stack from one file; BuildKit is the fast, modern build engine. Both ship with current Docker.
The Open Container Initiative standardises the image and runtime formats. containerd is the runtime underneath Docker — and under much of the cloud.
Daemonless, largely drop-in CLIs that build and run the same OCI images — no Docker Desktop licence required. Common in security-conscious shops.
Docker Engine is free and open source; Docker Desktop is not, for larger organisations. Since 2021, Docker Desktop requires a paid subscription for companies above Docker's size threshold (currently >250 employees or >$10M annual revenue). The images and the Engine stay free — it's specifically the Desktop app that's licensed. Teams that hit the threshold either buy the subscription or switch to a free alternative (Podman, Rancher Desktop, plain Engine on Linux). Worth checking before a finance surprise lands.
Docker is brilliant at building an image and running a few containers on one machine. Running hundreds of containers across many machines — with health checks, auto-restart, rolling updates and scaling — is a different job called orchestration. The image Docker produces is the unit that every orchestrator and managed platform consumes.
containerd — your images are unaffected, because they're OCI-standard.)Most teams should resist jumping to Kubernetes. The healthy path: Docker locally → Compose for the dev stack → a managed service (Cloud Run / Fargate) for production. Reach for Kubernetes only when you genuinely have the scale, the multi-team org, and the platform expertise to justify its considerable complexity. The container image you built on day one carries through every step without change — that portability is the point.
Containers are close to a default for server software in 2026 — but they're not free of cost, and some workloads are better served without them.
Two habits separate smooth Docker shops from painful ones. Pin base-image versions (node:22-alpine, not node:latest) so a rebuild next month produces the same thing. And keep images small — start from -alpine or -slim bases and use multi-stage builds to leave build tools out of the final image. A bloated, floating-tag image is a slow deploy and a future surprise.
Docker's value lands hard in SA delivery conditions: patchy connectivity, load-shedding, lean teams, and FX-priced cloud all reward an artefact you can rebuild identically and run anywhere.
When a machine dies mid-load-shedding or a developer's laptop is swapped, a container image means the environment comes back exactly as it was — no day-long "set up the dev box" ritual reconstructed from memory. The image is the source of truth for the runtime, and it lives in a registry you can pull from the moment power and connectivity return.
Containers pack many services onto one modest VM, which matters when every cloud rand is FX-exposed. A small Hetzner or local-provider box running several containers often does the work of multiple pricier managed services. And because images are portable, you keep the freedom to move between providers — or to af-south-1 for residency — without re-architecting.
For small SA studios and lean in-house teams, docker compose up turning a new hire's first day into a single command — database, cache, app, all running — is a real productivity multiplier. It also makes handovers between a studio and a client's internal team clean: the environment ships as code, not as tribal knowledge.
node:22-alpine) is a runtime decision.frappe_docker setup) — a real-world multi-container stack.Official Docker documentation, the Dockerfile and Compose references, and the OCI standard. Docker Desktop licensing terms change — confirm the current thresholds on Docker's pricing page before assuming. Last reviewed 2026-06-18.