Cloud Native 24 min read

Understanding Container Runtimes: From Low‑Level to High‑Level (containerd, CRI‑O, Docker)

This article explains the role of container runtimes, distinguishes low‑level, high‑level, and sandbox runtimes, and compares three major implementations—containerd, CRI‑O, and Docker—detailing their architecture, image handling, networking, storage, and integration with OCI specifications.

Open Source Linux
Open Source Linux
Open Source Linux
Understanding Container Runtimes: From Low‑Level to High‑Level (containerd, CRI‑O, Docker)

In computing, a runtime refers to the phase of a program's lifecycle when it is executed; a container runtime is software that runs and manages containers, handling image loading, resource isolation, and lifecycle management.

Types of Container Runtimes

Low‑level runtime : Provides basic isolation and lifecycle management using Linux cgroups and namespaces. Examples include Docker's runc and lxc. It is lightweight and high‑performance but lacks advanced features.

High‑level runtime : Builds on low‑level runtimes and adds richer features such as networking, storage, monitoring, image transfer, and management tools. Examples include Docker, containerd, and CRI‑O. It offers more functionality at the cost of complexity.

Sandbox or virtualization runtime : Uses sandbox or virtualization technologies to achieve stronger isolation and security, e.g., gVisor and Kata Containers, but incurs higher performance overhead.

Low‑Level Container Runtime

A low‑level container runtime (Low level Container Runtime) implements the OCI spec to receive a rootfs and a config.json and run an isolated process.

It only runs processes in isolated resource spaces and does not provide storage or network implementations; these must be supplied externally (e.g., via CNI for networking or CSI for storage).

Recognizes only rootfs and config.json, not full images; cannot build, push, or pull images.

Does not provide network implementation; external CNI plugins are required.

Does not provide persistent storage; users must mount host directories or use CSI drivers.

Bound to specific operating systems (e.g., runc runs only on Linux, runhcs only on Windows).

When a runtime addresses one or more of these limitations, it becomes a high‑level container runtime.

High‑Level Runtime First Task

The primary responsibility of a high‑level runtime is to bridge the OCI image spec and runtime spec, efficiently converting an image to a rootfs and generating a config.json. This involves image pulling, storage, layer extraction, and merging layers into a rootfs.

containerd

containerd

is a highly modular high‑level runtime where all components are loaded as RPC services (gRPC or TTRPC). Modules such as Content, Images, Snapshot, Containers, Diff, and Tasks are plug‑in based and can be combined to provide namespace isolation, image handling, and container process management.

Content : Indexes image layers by hash (usually SHA‑256) for fast lookup and labeling, stored in boltDB.

Images : Stores reference‑to‑manifest mappings, building complete image metadata.

Snapshot : Manages extracted filesystem layers and work layers, supporting various UnionFS drivers (overlay, aufs, btrfs).

Containers : Stores container metadata, including low‑level runtime description, snapshot key, image reference, and labels.

Diff : Computes differences between image layers and filesystem layers, verifying diffID values. containerd provides namespace isolation by placing module data in separate directory trees, allowing it to serve both Docker and Kubernetes simultaneously.

The Tasks module (runtime.PlatformRuntime) manages container processes and interacts with low‑level runtimes via shim processes. Since version 1.2.0, Tasks supports Windows and is platform‑agnostic.

When a container is started, containerd creates a container object, converts snapshots to mount points, combines them with the OCI spec and low‑level runtime info, and hands the request to the shim process, which then launches the container.

Using a shim isolates the container process from containerd; after a crash, containerd can quickly restore communication with the shim via its socket, enabling fast recovery.

CRI‑O

CRI‑O implements high‑level runtime functionality using several open‑source Go libraries rather than RPC protocols. Its core libraries include containers/image for image download and containers/storage for storage.

LayerStore : Handles image layers and filesystem layers, creating layer directories via a filesystem driver (e.g., overlay) and applying diffs.

ImageStore : Manages image metadata (manifest, config, signature) and indexes it in JSON files.

ContainerStore : Manages container metadata; its workflow mirrors ImageStore but operates in read‑write mode.

CRI‑O relies on CNI plugins (default path /opt/cni/bin) to provide networking. After a sandbox container is created, CRI‑O obtains the network namespace path ( /proc/{pid}/ns/net) and hands it to CNI, which configures an interface and IP address.

Configuration such as hostname and DNS is applied via file mounts rather than CNI.

Docker

Docker Engine is a comprehensive high‑level runtime consisting of the daemon dockerd, a REST API, and the Docker CLI. It handles image building, distribution, storage, and networking.

Image building uses a Dockerfile and commands such as docker build. Each Dockerfile instruction creates intermediate images or containers; the final image is tagged and stored.

Docker’s storage model extracts image layers to a filesystem (e.g., overlay2) and indexes them by chain ID. It does not store raw tarballs.

Network endpoints are created on the docker0 bridge, with IP allocation via IPAM. Port publishing adds iptables rules or runs a proxy to forward traffic.

When launching a container, Docker generates a read‑write layer, merges it with extracted layers via UnionFS, creates OCI spec files ( config.json, /etc/hosts, etc.), and forwards the request to containerd, which then uses the shim to start the container.

Summary

The article outlined the fundamentals of container runtimes—low‑level, high‑level, and sandbox types—and compared three major implementations: containerd, CRI‑O, and Docker. Docker provides the most feature‑rich, high‑level experience, while containerd and CRI‑O offer modular, lightweight alternatives that integrate tightly with Kubernetes.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Dockercontainerdcontainer-runtimeOCICRI-O
Open Source Linux
Written by

Open Source Linux

Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.