DevOps / Container Landscape
What to build containers with, and where to run them
Two separate decisions get treated as one. The first is which engine builds and runs images on a laptop, a CI runner, and a server. The second is what schedules them once there is more than one box - and that is where teams routinely buy Kubernetes for a problem Docker Compose already solved. This page settles both, in that order.
Reviewed August 2026. Back to DevOps guides.
The stack is smaller than the marketing suggests
An OCI image is a standard. Any engine can build it, any engine can run it, and any registry can store it. That makes the engine choice far less consequential than vendor pages imply - the artifact is portable no matter what produced it, which is why hybrid setups are normal rather than exotic.
Underneath every option here sits containerd or a close equivalent doing the actual work: pulling images, managing snapshots, talking to runc. Docker, Podman, and Kubernetes are all interfaces over roughly the same machinery. What differs is the security model, the daemon, and the tooling wrapped around it.
So spend your decision budget on the second question. Choosing Docker over Podman costs you an afternoon if you change your mind. Choosing Kubernetes costs you an engineer.
The engines, with verdicts
Docker
The local development default
Still the smoothest experience on a developer machine, and the one every tutorial, base image, and CI action assumes. Docker Desktop bundles the VM, the GUI, Compose, and BuildKit into something that works on macOS and Windows without thought. The friction is licensing and footprint: Desktop requires a paid subscription once a company passes 250 employees or $10M in revenue, running from about $9 to $24 per user per month, and the daemon holds roughly 140 to 180 MB of RAM whether or not anything is running. It also runs as root by default, which is a conversation on a shared server. docker.com
Verdict: Keep it on laptops. Check the headcount threshold before assuming it is free.
Podman
Servers, CI, and anywhere audited
Daemonless and rootless by default, which removes the always-on root process that makes security teams unhappy and consumes memory for nothing. Zero idle footprint, a CLI that is deliberately argument-compatible with Docker, a Docker-compatible socket for tools that expect one, and systemd integration through Quadlet so a container is just another unit the machine starts. Reported share is around 19 percent and rising fastest in finance, healthcare, and the public sector. Rough edges remain on macOS and in Compose corner cases. podman.io
Verdict: The better answer on servers and CI runners, and free at any company size.
containerd
The layer you already run
A CNCF graduated runtime that sits under Docker and under essentially every managed Kubernetes cluster. You do not choose containerd so much as discover you are on it, usually while debugging why docker ps shows nothing on a Kubernetes node. nerdctl gives it a Docker-shaped CLI and crictl gives it a Kubernetes-shaped one. Direct use makes sense on minimal hosts where you want a runtime and nothing else. containerd.io
Verdict: Not a competitor. Learn the CLIs so you can debug a node.
The pattern that actually won
About 34 percent of organizations now run Docker on developer machines and Podman in CI and production. The image is identical either way, so this costs nothing and buys a rootless server-side runtime plus one fewer paid seat per developer.
The orchestration ladder
Climb one rung at a time, and only when the rung you are on is visibly failing. Every step up costs operational capacity you have to take from somewhere.
| Rung | Fits when | You give up |
|---|---|---|
| Docker Compose | Three to five services on one server, one team, a deploy window measured in seconds of downtime you can accept. | Autoscaling, and surviving the loss of that one machine. |
| Serverless containers | You outgrew one box but not one team. Cloud Run, ECS Fargate, App Runner, Fly.io, Container Apps. | Portability and per-request cost predictability under spiky load. |
| k3s or k0s | You want the Kubernetes API and manifests on your own hardware, on one or a few nodes. | Someone else patching the control plane. You now own upgrades. |
| Managed Kubernetes | Eight or more independently deployed services, two or more teams shipping without coordinating, uptime that must survive a node failing. | Simplicity, and a meaningful share of somebody's week, forever. |
The 2026 consensus on this is unusually clear: below roughly fifteen engineers and without hundreds of services, Kubernetes is a complexity tax that buys nothing. It is a system that requires a person - not a person who has read the docs, a person who has debugged an eviction at 2am. Managed control planes remove some of that work and none of the rest.
Docker Swarm sits slightly off the ladder. It is simpler than Kubernetes and genuinely fine for a handful of nodes, and Dokploy builds its whole multi-server story on it - but the surrounding ecosystem stopped growing years ago, so choosing it for new work means accepting that you are on your own for tooling.
Gotcha: Kubernetes 1.35 shipped in-place pod resource updates as generally available, so CPU and memory can be adjusted without restarting pods. Genuinely useful - and still not a reason to adopt Kubernetes if you are on rung one.
Image habits that pay for themselves
- Multi-stage builds, always. Compile in a fat stage, copy the artifact into a slim or distroless runtime stage. It cuts image size and removes the compiler from anything an attacker can reach.
- Pin the base image by digest for production. A floating tag means your reproducible build quietly is not one.
- Order layers by how often they change. Dependency manifests and install steps first, source last, so a code edit does not invalidate the install cache.
- Run as a non-root user. One USER line. Podman gives you rootless on the host; this gives you non-root inside the container, and you want both.
- Write a real .dockerignore. Shipping .git and node_modules into the build context is the most common reason a build is slow and an image is large.
- Tag with the commit SHA, not just latest. That single habit is what makes the rollback path in the CI/CD pipeline guide possible.
Our pick
Docker on laptops, Podman on servers, Compose until it hurts
Build locally with Docker because the experience is better and every teammate already knows it. Run in CI and in production with Podman because rootless and daemonless is strictly better on a machine you do not sit in front of, and because it removes a per-seat licence question at exactly the moment headcount makes it expensive. The image does not care, so this hybrid costs you nothing.
For orchestration, stay on Docker Compose on a single server for as long as it works - which for most products is longer than anyone admits. When one box stops being enough, the next rung is a serverless container platform such as Cloud Run, ECS Fargate, or Fly.io, not Kubernetes. Take managed Kubernetes when you have several teams shipping independently and an uptime commitment that must survive hardware failing, and take k3s when you want the same API on hardware you own.
If you are one team on one server, the honest answer is that a VPS with a control plane beats every orchestrator on this page.
Where to go next
Docker cheatsheet
Build, run, volumes, networks, and Compose commands by task.
Open the referenceDocker vs Podman
Rootless security, licensing, and Compose compatibility head to head.
Read the verdictkubectl cheatsheet
Inspect, debug, deploy, and switch contexts without guessing.
Open the referenceHosting layer
Who actually runs your containers, priced side by side.
Browse the layerProvisioning the clusters and registries these images live in is a separate discipline - infrastructure as code covers OpenTofu, Terraform, and Pulumi for that job.