Advertisement

Cloud · kubernetes, docker, containers, platform-engineering

Kubernetes vs Docker: which layer does what, and what each one costs

Docker builds images and runs containers on one host; Kubernetes schedules and heals containers across many. They are different layers rather than rivals, and only the orchestrator arrives with a control plane and a platform team attached.

Kubernetes vs Docker: which layer does what, and what each one costs Cloud

Key points

  • The two names sit on different layers: Docker supplies the image build and a single-host runtime, while Kubernetes decides which host runs a container and keeps the declared state true.
  • Kubernetes stopped using the Docker daemon as its node runtime when dockershim was removed in v1.24, but images built with Docker still run, because containerd and CRI-O implement the same interfaces.
  • What the orchestrator adds over one machine is scheduling, service discovery and load balancing, self-healing, rolling updates with rollback, configuration distribution and horizontal scaling.

Three layers, and only one of them is a product you buy

The comparison goes wrong in its first sentence, because the two names sit on different layers. An image is built and shipped by tooling — a Dockerfile, an image builder, a registry — and a runtime on a host turns that image into a running process. Kubernetes sits above both: it decides which host runs the container, restarts it when it fails, and exposes it to traffic. Docker ships the builder and a runtime; Kubernetes ships neither.

The image format is why the two work together at all. Docker images follow the Open Container Initiative image specification, and so do the runtimes Kubernetes talks to, which is why an image built on a laptop runs on a cluster that has never had a Docker daemon installed on it.

What each layer is responsible for.
Docker's layerKubernetes' layer
Image format and build toolingA Dockerfile, the docker build command and BuildKit produce an image; docker push sends it to a registryPulls images from a registry and runs them; it never builds one
Container runtimeThe Docker daemon creates and manages containers on the host it runs onKubelet on each node calls a Container Runtime Interface implementation, usually containerd or CRI-O
Placement and schedulingContainers run on the host where you started themThe scheduler places pods on nodes using the requests, limits and constraints you declare
Service discovery and load balancingContainers on a user-defined network reach each other by name; ports are published on the hostEach workload gets a stable Service and DNS name, and kube-proxy programs the rules that reach it
Self-healingA restart policy replaces a failed container on the same hostControllers recreate failed pods, move the pods of a lost node and hold the declared replica count
Updates and rollbackYou stop and start containers yourself, or run the Compose command againA Deployment replaces pods gradually and can be reversed to the previous revision
Configuration and secretsEnvironment files and mounted files are passed in at run timeConfigMaps and Secrets are distributed to pods and versioned alongside the workload
ScalingA larger host, or more containers on the same oneA horizontal pod autoscaler adds replicas, and a cluster autoscaler adds the nodes they need

What Docker owns, and where the daemon stops

Docker is a platform for building, shipping and running applications: a command-line client, a daemon that manages images, containers, networks and volumes, and Compose, which describes a multi-container application in one file and starts it with one command. On a single host, that is a complete answer to running software.

Build tooling is the part that carries over unchanged. A Dockerfile, an image build and a registry push are the same work whether the image lands on one server or in a cluster, and Docker's own documentation treats the image, the Dockerfile and the registry flow as the core of the platform.

What changes is everything downstream of the image: who starts it, where it runs, how many copies exist, and what takes over when one stops. That is the orchestrator's job, and it is the layer Kubernetes was written for.

Advertisement

Containerd, CRI-O, and why "Kubernetes deprecated Docker" is off by a layer

The folklore comes from a real change with a narrower scope. Kubernetes used a shim called dockershim to talk to the Docker daemon, because that daemon does not implement the Container Runtime Interface; the project deprecated the shim and removed it in v1.24. Kubelet now speaks to a runtime that does implement the interface, and the two common ones are containerd and CRI-O.

The removal did not break images. Docker-produced images follow the OCI image specification and still run, because what changed is the runtime that starts the container, not the artifact it starts. The practical loss was narrower: a node no longer carries the docker command line, and anything that reached into the Docker socket on that node needs another route.

So the accurate sentence is that Kubernetes stopped using the Docker daemon as its node runtime, not that Kubernetes dropped Docker. The second accurate sentence is that the two were never alternatives: you can build an image with Docker and run it on a cluster that has no Docker installed anywhere.

What Kubernetes adds over one machine

The control plane is what you are buying. The API server accepts the objects you declare, etcd stores them, the scheduler assigns pods to nodes, and the controller manager runs the control loops that keep comparing declared state with observed state. On every node, kubelet starts the containers and kube-proxy programs the rules that make Services reachable.

Service discovery and load balancing come with that. A workload gets a stable name and a virtual address instead of a host and a port, and traffic is spread across whichever replicas exist at that moment — the problem a single-host setup solves by hand, one published port at a time.

Self-healing and safe updates run on the same loop. A Deployment declares how many replicas should exist and how quickly to replace them; failed pods are recreated, a node that stops reporting has its pods moved, and a rollout that goes wrong can be reversed to the previous revision. Configuration is distributed to pods rather than baked into images, and replica count can follow a metric instead of a change ticket.

Advertisement

What Kubernetes costs: a control plane, three upgrades a year, and choices

The control plane is the first cost. Self-managed means running the API server, etcd, the scheduler and the controller manager yourself, with quorum, backups and an upgrade order that has to be right. Managed means someone else runs those components, and sometimes at no charge: Azure bills nothing for cluster management on the AKS Free tier, which its documentation recommends for clusters below ten nodes, and puts an uptime SLA on the Standard tier at 99.95% of API server availability with availability zones, 99.9% without.

Upgrades are the second cost, and they arrive on someone else's schedule. Kubernetes maintains release branches for the three most recent minor versions, each with roughly a year of patch support, and a new minor version lands about every four months: 1.35 in December 2025, 1.36 in April 2026, 1.37 in August 2026. A cluster that falls outside the supported skew is the cluster nobody wants to upgrade on a Friday.

The third cost is the choices a distribution no longer makes for you. Someone has to select and operate a network plugin, an ingress or Gateway API implementation, a storage driver, a metrics and logging stack and a policy layer, then keep the manifests for all of it in review. That work has a name — the platform team — and a salary attached to it.

When Compose on one or two hosts is the right answer

Compose defines a multi-container application in a single file and starts it with one command, and for a lot of estates that is the entire deployment mechanism. It adds no control plane to patch, no ingress controller to configure, no version skew to track and no second machine to keep in sync.

The limits are structural rather than embarrassing. Compose does not place work across hosts, so a dead server is an outage until a person restores it; service discovery stops at names on a Docker network; and releasing a new version means deciding for yourself how to avoid a gap in service. If two hosts behind a load balancer already meet the uptime the business pays for, that is the cheaper architecture, and orchestration has to earn its place on top of it.

# The whole deployment mechanism, on one host.
services:
  api:
    image: registry.example.com/api:1.42.0
    ports:
      - "8080:8080"
    environment:
      DATABASE_URL: postgres://db:5432/app
    depends_on:
      - db
  db:
    image: postgres:17
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

Advertisement

The decision: team size, service count, and the uptime you pay for

Running Kubernetes is a commitment before it is a technology decision. It implies someone who can read a control-plane upgrade and roll it back, an on-call rotation that can debug a pod which will not schedule at 03:00, and a change process where manifests go through review like any other code. A team of four generalists looking after three services rarely has that person; a team of forty with a platform group usually does.

The deciding numbers are unglamorous. Under about ten services on one or two hosts, Compose and a load balancer carry you; somewhere between ten and thirty, scheduling, health checks and rolling updates start repaying their cost, and a managed control plane is usually cheaper than hiring for one; above that, the orchestrator stops being a choice at all. A compliance requirement for reproducible, auditable deployments moves the line downward.

The tiebreaker is the uptime the business actually pays for. If a Saturday-night outage costs a support ticket and an apology, highly available architecture is something you do not need to fund. If it costs revenue per minute or triggers a contractual credit, then node-level self-healing and a control plane with an SLA are what you are buying, and the cluster itself is the cheapest part of that decision.

Advertisement

Sources 6

Read next

More Cloud