🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

What Is a Container Runtime? Explained Simply (2026)

Every container needs a runtime to actually run. Docker has one. Kubernetes has one. They're different. Here's what a container runtime is, why it matters, and how containerd, runc, CRI-O, and Docker relate to each other.

DevOpsBoysMay 22, 20265 min read
Share:Tweet

When you run a container — with Docker, Kubernetes, or anything else — something has to actually create and run that container. That something is the container runtime.

Most engineers use containers every day without knowing what the runtime is or why it matters. Here's a clear explanation.


What a Container Runtime Does

A container runtime is software that:

  1. Creates and manages container processes — starts them, stops them, monitors them
  2. Sets up isolation — uses Linux namespaces and cgroups to isolate the container from the host
  3. Manages container images — pulls them from registries, stores layers, unpacks them
  4. Handles networking and storage — attaches network interfaces and volumes to containers

Without a container runtime, you can't run containers. It's the engine underneath everything else.


The Two Levels of Container Runtime

This is where it gets a bit confusing, so let's separate them clearly.

Low-Level Runtime (OCI Runtime)

Creates and runs the actual container process. Directly interacts with the Linux kernel — namespaces, cgroups, filesystem.

The standard here is the OCI Runtime Specification (Open Container Initiative).

Main example: runc

  • Created by Docker, donated to OCI
  • Almost every container in production runs via runc (directly or indirectly)
  • Very minimal: takes a container bundle, calls the kernel APIs, starts the process

There are alternatives: crun (faster, written in C), gVisor/runsc (sandboxed runtime for security), kata-containers (VM-based isolation).

High-Level Runtime (Container Manager)

Manages the full container lifecycle: pulling images, setting up networking, monitoring containers, providing APIs for other tools.

The high-level runtime talks to the low-level runtime to actually start containers.

Main examples:

  • containerd — most widely used in production today
  • CRI-O — designed specifically for Kubernetes
  • Docker Engine — the original, now wraps containerd underneath

How Docker Fits In

When you run docker run nginx, here's what actually happens:

You → Docker CLI
         ↓
    Docker Daemon
         ↓
     containerd       ← high-level runtime
         ↓
      containerd-shim
         ↓
        runc           ← low-level runtime (creates actual container)
         ↓
   Linux Kernel (namespaces, cgroups)

Docker is not really one thing — it's a tool (the CLI), a daemon, and under the hood it uses containerd and runc.

When Kubernetes removed "Dockershim" in 2022, it didn't remove the ability to run Docker-built containers. It removed the shim that made Docker (the daemon) work as a Kubernetes runtime. containerd — which Docker itself uses — became the default Kubernetes runtime.


How Kubernetes Uses Container Runtimes

Kubernetes doesn't talk to container runtimes directly. It uses a standard interface: the Container Runtime Interface (CRI).

CRI is a gRPC API that Kubernetes defines. Any runtime that implements CRI can work with Kubernetes.

Kubernetes kubelet
      ↓
    CRI (gRPC API)
      ↓
  containerd or CRI-O
      ↓
     runc
      ↓
   containers

containerd and CRI-O both implement CRI. Docker Engine didn't (which is why Dockershim was needed — it was a translation layer). That translation layer was removed in Kubernetes 1.24.


containerd

The most widely deployed container runtime today. Used by:

  • AWS EKS (default)
  • GKE
  • AKS
  • Most Kubernetes distributions

containerd handles:

  • Pulling and storing images (content store)
  • Creating and managing containers
  • Snapshotting filesystems
  • Namespace isolation for multiple consumers (Kubernetes gets its own namespace)
bash
# Check which runtime your Kubernetes node uses
kubectl describe node <node-name> | grep "Container Runtime"
# Container Runtime Version: containerd://1.7.x
 
# On the node directly, use ctr (containerd CLI)
ctr images list
ctr containers list

CRI-O

A lightweight runtime built specifically for Kubernetes. If containerd is a general-purpose runtime that supports Kubernetes among other things, CRI-O is designed purely to run Kubernetes workloads.

Used by:

  • Red Hat OpenShift (default)
  • Some enterprise Kubernetes distributions

Smaller footprint, fewer features than containerd, but very stable for Kubernetes use.


gVisor and Kata Containers — Security Runtimes

For workloads that need extra isolation (multi-tenant environments, untrusted code):

gVisor (runsc): Intercepts system calls in user space. Container processes don't touch the real kernel directly — gVisor acts as a kernel interceptor. Provides strong isolation, some performance overhead.

yaml
# Use gVisor runtime class in Kubernetes
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
---
spec:
  runtimeClassName: gvisor  # Add to pod spec

Kata Containers: Each container runs in its own lightweight VM with a minimal kernel. Very strong isolation, heavier than gVisor, but stronger security guarantees.


What OCI Is

OCI = Open Container Initiative. An industry standards body (under Linux Foundation) that defines:

  • OCI Image Spec — what a container image looks like (layers, manifest, config)
  • OCI Runtime Spec — how a container runtime must start containers
  • OCI Distribution Spec — how registries serve images

Any Docker image is an OCI image. Any OCI image runs on any OCI-compatible runtime. This is why a container built with Docker runs on containerd, CRI-O, or anything else.


Which Runtime Should You Care About?

For most engineers: You never configure the container runtime directly. Kubernetes uses containerd on most managed clusters. You don't interact with it.

What you should know:

  • Your containers are likely running via containerd → runc
  • Images are OCI-compatible and portable
  • Runtime class (runtimeClassName) lets you choose different runtimes per workload if needed

If you're a platform engineer or cluster admin:

  • Know how to check which runtime is running (kubectl describe node)
  • Understand containerd's configuration (/etc/containerd/config.toml)
  • Know how to configure mirror registries and insecure registries in containerd config

If you're building for security:

  • Know that gVisor and Kata exist
  • Understand the tradeoffs: isolation vs performance

Quick Summary

ComponentWhat it is
runcLow-level OCI runtime — creates actual container processes
containerdHigh-level runtime — manages images, containers, used by K8s and Docker
CRI-OHigh-level runtime — built specifically for Kubernetes
Docker EngineUses containerd internally; adds developer UX and CLI
CRIKubernetes interface for talking to any container runtime
OCIStandards that make containers portable across runtimes

The container ecosystem looks complicated but it's really just: standards at the bottom (OCI), a layer that manages containers (containerd/CRI-O), and tools that use those (Kubernetes, Docker).

Related: What Is a Pod Lifecycle in Kubernetes | Docker Security Best Practices | What Is a Container Registry

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments