Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 9 min read

Kubernetes vs Docker: They Aren't Competitors (Here's What Each Actually Does)

Kubernetes vs Docker explained plainly: Docker builds and runs containers, Kubernetes orchestrates them. Learn what each does and whether you need an orchestrator yet.

  • #kubernetes
  • #docker
  • #containers

“Should we use Kubernetes or Docker?” is one of the most common questions I hear from engineers deciding what to learn next, and it’s built on a small misunderstanding. Docker and Kubernetes don’t solve the same problem, so pitting them against each other is a bit like asking whether you need an engine or a fleet of trucks. Once you see where each one sits in the stack, the “kubernetes vs docker” question mostly answers itself — and the real question underneath it becomes clear: do I need an orchestrator yet?

What Docker actually does

Docker is a tool for building and running containers on a single machine. That’s the whole job, and it does it well.

Concretely, Docker gives you three things:

  • A way to build an image from a Dockerfile — your app plus its dependencies, frozen into a portable artifact.
  • A way to run that image as a container — an isolated process with its own filesystem and network namespace.
  • A registry workflow to push and pull those images so other machines can run them too.

Here’s the whole loop in practice:

# Build an image from the Dockerfile in the current directory
docker build -t myapp:1.0 .

# Run it, mapping container port 8080 to host port 8080
docker run -d --name myapp -p 8080:8080 myapp:1.0

# See it running
docker ps

That’s Docker’s lane: package an app, run it, ship it. Notice what’s not there. Nothing restarts the container if the host reboots. Nothing spreads copies across ten servers. Nothing shifts traffic when one instance gets unhealthy. Docker runs containers; it doesn’t manage a fleet of them. That’s not a criticism — it’s just the boundary of the tool.

What Kubernetes actually does

Kubernetes is an orchestrator. It assumes you already have containers and a pile of machines, and its job is to run those containers across those machines the way you asked, and to keep doing so as things fail.

You hand Kubernetes a desired state — “I want three copies of this container running, always” — and its control loop works to make reality match. That’s the mental shift: with Docker you issue commands; with Kubernetes you declare an outcome and let the system reconcile toward it.

The things Kubernetes adds on top of “a running container” are exactly the things a single docker run can’t do:

  • Scheduling — deciding which machine each container runs on, based on available CPU and memory.
  • Self-healing — restarting containers that crash, and rescheduling them elsewhere if a whole node dies.
  • Scaling — running many replicas and adjusting the count, by hand or automatically.
  • Service discovery and load balancing — giving a stable name and address to a set of replicas that are constantly coming and going.
  • Rollouts — replacing old versions with new ones gradually, and rolling back if it goes wrong.

Here’s the same app as before, but described to Kubernetes as a Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:1.0
          ports:
            - containerPort: 8080

Notice I never said where to run those three replicas or how to restart them. That’s the point. You describe what you want; the orchestrator figures out the placement and keeps it true.

So which is it — Kubernetes vs Docker?

Neither, really, because they operate at different layers. Docker (or another builder) produces the container. Kubernetes takes containers and runs them at scale across machines. In a typical production setup you use both: Docker-style tooling in your build pipeline to produce images, and Kubernetes to run those images in the cluster.

Here’s the plain comparison I sketch out for people:

DockerKubernetes
Primary jobBuild and run containersOrchestrate containers across machines
ScopeOne hostA cluster of many hosts
You give itCommands (build, run)Desired state (YAML manifests)
Restarts a crashed app?No, not on its ownYes, automatically
Spreads replicas across nodes?NoYes
Load balances across instances?NoYes
Good fit forLocal dev, CI builds, small single-host deploysMulti-service systems that need scale and resilience

If there’s one line to remember: Docker gives you a container; Kubernetes gives you a system that keeps containers running the way you asked.

The runtime relationship (and the dockershim confusion)

This is where a lot of the “Docker vs Kubernetes” anxiety actually comes from, so let me walk through it calmly.

A few years back, people saw headlines about Kubernetes “removing Docker” and understandably panicked. Here’s what really happened, and why it’s a non-event for almost everyone.

Kubernetes doesn’t run containers directly. It talks to a container runtime through a standard interface called the CRI (Container Runtime Interface). The common runtime today is containerd — which, incidentally, was originally extracted from Docker itself. Docker the product wasn’t built to speak CRI, so for years Kubernetes used a shim called dockershim to translate between them. Maintaining that shim was extra work for the Kubernetes project, so in version 1.24 (2022) they removed it. Kubernetes now talks to containerd (or another CRI runtime) directly.

The part that matters: this does not affect your images. Docker builds images to the OCI (Open Container Initiative) standard, and containerd runs OCI images. So an image you build with docker build runs on Kubernetes exactly as before — the dockershim removal changed a plumbing detail inside cluster nodes, not the images you ship. If you’re building images with Docker and running them on a managed Kubernetes service, you almost certainly never noticed.

The one place it mattered was for people who ran the full Docker daemon on the cluster nodes themselves and relied on it being there. Those setups needed to switch the node runtime to containerd — which most managed providers handled for their users automatically. For everyone building images and deploying them, nothing changed.

So: Docker and Kubernetes aren’t fighting over the runtime. They quietly share the same lineage.

Docker Compose vs Kubernetes for multiple containers

There’s one spot where the two genuinely overlap, and it trips people up: running several containers together.

Docker Compose lets you define a multi-container app in a single docker-compose.yml — a web service, a database, a cache — and bring them all up with one command on one machine. It’s excellent for local development and for simple single-host deployments. It’s easy to read, easy to reason about, and there’s very little to operate.

Kubernetes can do the same multi-container job, but across a cluster, with self-healing and scaling built in. The cost is complexity: more concepts, more YAML, more moving parts to run and secure.

The honest guidance is about scope:

  • One machine, a handful of services, and you can tolerate a reboot causing a blip? Compose is probably right. Don’t reach past it.
  • Many machines, you need replicas spread for resilience, zero-downtime rollouts, and automatic recovery? That’s the job Kubernetes was built for.

Compose and Kubernetes aren’t rivals either — they’re the same idea (declare a set of services) aimed at very different scales.

Do you actually need Kubernetes yet?

This is the question hiding inside most “kubernetes vs docker” debates, and I’d rather answer it honestly than sell you an orchestrator.

Kubernetes is a genuinely capable system, and it earns its keep at scale. But it is not free. It adds real operational weight — a cluster to run and upgrade, networking and RBAC to understand, and a new category of things that can page you at 3 a.m. The complexity isn’t wasted when you need what it provides. It’s pure overhead when you don’t.

Signals you’re probably ready for it:

  • You’re running many services that need to talk to each other, and wiring them by hand has gotten fragile.
  • You need to survive a single machine dying without human intervention.
  • You want automated, incremental rollouts and easy rollbacks.
  • You’re already scaling instances up and down and doing it manually hurts.
  • You have — or can build — the operational muscle to run a cluster.

Signals you don’t need it yet:

  • You have one app, or a few, and a single beefy VM handles the load fine.
  • Your team is small and nobody wants to become a part-time cluster operator.
  • A managed platform (a PaaS, a container service, even a couple of VMs behind a load balancer) already meets your uptime needs.
  • You’re reaching for Kubernetes because it’s on résumés, not because a problem is pushing you there.

That last one is worth sitting with. The boring answer is usually the right one here: plenty of healthy systems run on Docker images deployed to a managed container service or a small VM fleet, and their teams sleep fine precisely because they didn’t take on a cluster they didn’t need. In my experience, the complexity you adopt before you need it tends to become the complexity that pages you first. Adopt an orchestrator when a real operational pain is pushing you toward one — blast radius you can’t contain, recovery you can’t automate — not before.

And to be clear, this isn’t Kubernetes being bad. When you genuinely operate at fleet scale, hand-rolling scheduling and self-healing is far more painful than learning Kubernetes. The skill is matching the tool to the problem you actually have today.

Wrapping up

Docker and Kubernetes aren’t competing tools — they’re layers of the same stack. Docker builds and runs the container; Kubernetes runs a fleet of those containers and keeps them healthy. The real decision was never “which one,” it was “do I need an orchestrator yet?” — and it’s completely fine if the honest answer is not yet.

If you want to go deeper on either layer, I keep practical, production-oriented notes for both: the Docker toolkit for building and running containers well, and the Kubernetes toolkit for when you’ve decided you actually need the orchestrator. Learn them as layers, in that order, and the whole “vs” framing stops mattering.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.