Introduction
Containers have revolutionized how applications are deployed and managed in modern infrastructure. But what exactly is a container, and how do container runtimes make them work? This comprehensive guide explores the foundational concepts that power billions of containerized applications worldwide.
What is a Container?
A container is a standard unit of software that encapsulates application code along with its configuration files, libraries, and binaries. This ensures that the application can run reliably in various computing environments, from development laptops to production Kubernetes clusters.
Think of a container as a lightweight, isolated package containing everything your application needs to run. Unlike virtual machines that include an entire operating system, containers share the host OS kernel, making them significantly more efficient.
Container Images: The Blueprint
Before a container runs, it starts as a container image – the blueprint of containers. A container image contains all the components for an application to run:
- Application binaries
- Libraries and dependencies
- System tools
- Configuration parameters
During runtime, these container images become actual running containers.
Building Container Images
Container images are built using a set of instructions defined in a plain text file known as:
- Dockerfile (Docker standard)
- Containerfile (Open Container Initiative standard)
Tools like Buildah and Docker read these instructions to build images. Here’s a simple example:
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3
COPY app.py /app/
CMD ["python3", "/app/app.py"]
This Dockerfile creates an image with Ubuntu, Python 3, and your application included.
Container Runtimes: The Engine
Now comes the critical question: what actually runs and manages containers? The answer is container runtimes.
Container runtimes are responsible for the entire lifecycle of a container:
- Pulling images from container repositories
- Creating containers from images
- Managing container startup, execution, and shutdown
- Setting up networking and storage
- Interfacing with the host operating system
The Layered Architecture
Container runtimes operate in a layered architecture:

Figure 1 (from thesis): A containerized environment architecture consists of containers running on a container runtime. The runtime interfaces with the host operating system, which is layered over the underlying infrastructure.
Container Runtime Architecture: High-Level and Low-Level Runtimes
Container runtimes are categorized into two distinct types that work together seamlessly:
High-Level Container Runtimes
High-level container runtimes (also called container engines) are user-facing tools that [2]:
- Provide a daemon application that runs in the background
- Offer a CLI client for user interaction
- Expose an API for programmatic access
- Manage the abstract container lifecycle
Examples: containerd, CRI-O
Architecture Overview:

Figure 2 (from thesis): CLI interaction with container ecosystems: A user issues commands via a CLI to a high-level runtime, which then relays instructions to the low-level runtime, orchestrating direct container management and resource allocation.
Low-Level Container Runtimes
Low-level container runtimes focus on the technical implementation:
- Running containers and setting up isolation
- Creating Linux namespaces and cgroups
- Mounting container filesystems
- Implementing the Open Container Initiative (OCI) specification
Examples: runc, crun
How They Work Together
User CLI Command
↓
High-Level Runtime (containerd/CRI-O)
↓ (via gRPC over CRI protocol)
Low-Level Runtime (runc/crun)
↓
Container Execution & Isolation
Container Runtime Interface (CRI)
The Container Runtime Interface (CRI) is a protocol standardized by Kubernetes that enables orchestration platforms to interact with various container runtimes without recompilation.
CRI defines:
- gRPC protocol for communication between Kubelet and container runtime
- Standardized APIs for container lifecycle management
- Protocol buffers for efficient serialization
This standardization allows Kubernetes to work with any CRI-compliant runtime – a major architectural win for flexibility.
CRI-O: A CNCF-Graduated Runtime
CRI-O is a lightweight, open-source, high-level container runtime maintained by Red Hat, Intel, Suse, Hyper, and IBM.
CRI-O Container Lifecycle
1. User issues CLI command to CRI-O
↓
2. CRI-O checks local image cache
↓
3. If needed, pull image from registry
↓
4. Unpack container image to root filesystem
↓
5. Generate OCI runtime specification JSON
↓
6. Launch low-level runtime (e.g., crun)
↓
7. Low-level runtime creates namespace/cgroups
↓
8. Container executes
Key Characteristics
- Lightweight: Minimal footprint compared to Docker
- CRI Protocol Compliant: Works natively with Kubernetes
- OCI Compatible: Works with any OCI-compliant low-level runtime
- Storage Management: Uses containers/storage library for filesystem
containerd: The Industry Standard
As stated by the Cloud Native Computing Foundation, containerd is an industry standard runtime designed to be embedded in larger systems rather than used directly by end-users.
A Key Innovation: containerd-shim
containerd introduces the lightweight containerd-shim intermediary process:
containerd (high-level)
↓
containerd-shim (lifecycle manager)
├─ Mounts container filesystem
├─ Manages container state
└─ Unmounts on termination
↓
Low-level runtime (runc/crun)
↓
Container execution
The containerd-shim is crucial because:
- It manages container filesystem lifecycle
- It allows the low-level runtime to exit after container start
- It maintains container state without keeping processes running
- It enables resource cleanup
containerd Container Lifecycle
1. User CLI interaction with containerd
↓
2. Check image cache, pull if needed
↓
3. Unpack container image
↓
4. Generate OCI runtime specification
↓
5. Launch containerd-shim
↓
6. Shim invokes low-level runtime
↓
7. Container creation & execution
Key Differences: CRI-O vs. containerd
| Aspect | CRI-O | containerd |
|---|---|---|
| Primary Use | Kubernetes integration | Container runtime ecosystem |
| Intermediary | Direct | Uses containerd-shim |
| Packaging | Standalone | Core Docker component |
| Maintenance | Multiple organizations | CNCF ecosystem |
| Filesystem Mgmt | Direct / containers-storage | Via containerd-shim |
The Open Container Initiative (OCI) Standard
Both high-level runtimes and low-level runtimes conform to the OCI specification, which defines:
- Container Runtime Specification: How containers should behave
- Container Image Specification: Standard image format
- Image Distribution Specification: How images are shared
When a high-level runtime creates a container, it generates an OCI-compliant JSON specification file containing all container details. The low-level runtime then interprets this JSON and creates the appropriate Linux namespaces, cgroups, and mount points.
Container Networking and Storage
Networking
Container runtimes manage networking through:
- Linux namespaces (network isolation)
- Virtual network interfaces
- Bridge networking (multiple containers on host)
- Overlay networks (multi-host communication in Kubernetes)
Storage
Container runtimes handle storage via:
- Container storage library (containers/storage) for image layers
- Copy-on-write (CoW) filesystems for efficiency
- Volume mounting for persistent data
- Bind mounts for host filesystem access
Why Container Runtimes Matter
Container runtimes are the critical infrastructure that:
- Abstracts hardware complexity from applications
- Standardizes deployment across environments
- Enables Kubernetes orchestration
- Improves resource utilization
- Enhances security through isolation
Future Directions
The container runtime ecosystem continues evolving:
- CRUN improvements for alternative workloads (WebAssembly)
- Kata Containers for stronger isolation
- gVisor for advanced sandboxing
- Hybrid runtimes supporting multiple workload types
Conclusion
Container runtimes form the backbone of modern application deployment. Understanding the distinction between high-level runtimes (CRI-O, containerd) and low-level runtimes (runc, crun), and how they implement OCI standards, is essential for anyone working with containers and Kubernetes.
Whether you choose CRI-O for its Kubernetes-first design or containerd for its ecosystem integration, both represent mature, production-ready solutions for running containerized applications at scale.
Ready to dive deeper? Explore how container runtimes enable WebAssembly workloads in the next generation of cloud-native applications!
References
Based on “Exploring WebAssembly-Based Microservices Implementation & Deployment Methods in Kubernetes” by Micheal Choudhary (2024):
[7] “Docker: What is a Container?,” [Online]. Available: https://www.docker.com/resources/what-container/. [Accessed 1 October 2023].
[8] “OpenShift: Understanding containers,” [Online]. Available: https://docs.openshift.com/container-platform/4.12/nodes/containers/nodes-containers-using.html. [Accessed 30 November 2023].
[9] “Container Runtimes,” [Online]. Available: https://kubernetes.io/docs/setup/production-environment/container-runtimes/. [Accessed 6 May 2023].
[10] D. Zuev, A. Kropachev and U. Aleksey, “Container Runtime and Container Runtime Interface,” in Learn OpenShift, Packt Publishing, 2018, pp. 80-87.
[11] “Container Runtime Interface (CRI),” [Online]. Available: https://kubernetes.io/docs/concepts/architecture/cri/. [Accessed 5 October 2023].
[12] “Crun: A fast and low-memory footprint OCI Container Runtime fully written in C.,” [Online]. Available: https://github.com/containers/crun. [Accessed 3 May 2023].
[13] ”https://cri-o.io/,” [Online]. Available: cri-o. [Accessed 10 June 2023].
[14] S. Grunert, “Demystifying containers – part II: container runtimes,” [Online]. Available: https://www.cncf.io/blog/2019/07/15/demystifying-containers-part-ii-container-runtimes/. [Accessed 6 June 2023].
[15] “containerd-shim/main.go,” 17 June 2016. [Online]. Available: https://github.com/docker-archive/containerd/blob/a8c73b6959c7b63214bd6ed1e658a165dd61ec0e/containerd-shim/main.go. [Accessed 13 August 2023].
[16] “containerd: An open and reliable container runtime,” [Online]. Available: https://github.com/containerd/containerd. [Accessed 10 July 2023].
[17] “containerd Runtime v2,” [Online]. Available: https://github.com/containerd/containerd/blob/096e99fe7e3febdc96df26f743d45d18b8087b6d/runtime/v2/README.md. [Accessed 12 July 2023].