Container runtime vocabulary
Tags: docker, devops, containers, opensource
Published: 2023-04-23 22:00:00

Docker became the most popular standard of the containerization. It's so popular that almost everything in the containerized world is called Docker. You can't argue with that. What you can do is learning it. No matter if you are a developer, a sysadmin, or a DevOps engineer, you should know Docker to work with a modern infrastructure.

In this post, I will show you that **Docker is only a little part of the containerization now**.

So, why almost everything in the containerized world is called Docker❓ What is the difference between a container engine and a container runtime❓ Why is it so confusing❓ What are example tools we can call low-level container runtime and high-level container runtime❓

All these questions and more will be answering in this post.

> NOTE
> The terminology in the post is linked to each other. You can find:
>
> - internal links to other terms within the post
> - external links to home pages of tools
> - bold terms (they are described in the previous post of this series: [Container and image vocabulary](https://dev.to/zdybit/container-and-image-vocabulary-123k)).

## Table of contents

- [Table of contents](#table-of-contents)
- [Terminology schema](#terminology-schema)
- [Docker legacy](#docker-legacy)
  - [Docker breakup](#docker-breakup)
  - [Container runtime vs container engine](#container-runtime-vs-container-engine)
- [Tool categories](#tool-categories)
  - [container runtime - low-level](#container-runtime---low-level)
  - [container runtime - high-level](#container-runtime---high-level)
  - [container image build tool](#container-image-build-tool)
  - [container orchestrator](#container-orchestrator)
  - [daemon](#daemon)
- [Standards](#standards)
  - [Open Container Initiative](#open-container-initiative)
  - [OCI Image Format Specification (image-spec)](#oci-image-format-specification-image-spec)
  - [OCI Distribution Specification (distribution-spec)](#oci-distribution-specification-distribution-spec)
  - [OCI Runtime Specification (runtime-spec)](#oci-runtime-specification-runtime-spec)
  - [OCI Image Configuration](#oci-image-configuration)
  - [container image format](#container-image-format)
  - [image manifest](#image-manifest)
  - [image index](#image-index)
  - [registry, repository, tag](#registry-repository-tag)
- [Ending](#ending)

## Terminology schema

I prepared the next map 🗺️ with relations between terms for you. With it, we can continue our journey.

![schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mdi1x580uwvvghw3bpgo.png)

> **[The schema was edited on 26-apr-2023]**
> Podman itself is not a low-level container runtime. It uses crun by default to create and run containers.

## Docker legacy

A little historical overview is needed to fairly learn containerization tools and to finally answer the question *"why is everything called Docker?"*.

### Docker breakup

When Docker was spreading its popularity, it was a monolith tool. It could build and manage images, transfer them to/from a container registry, run and manage containers, interact with isolated applications and resources withing the containers, and more. Pretty much, isn't it?

Docker Inc. broken up its tool into the modules: [runC](https://github.com/opencontainers/runc), [containerd](https://containerd.io), [dockerd](https://docs.docker.com/engine/reference/commandline/dockerd/), and docker CLI client. Some of those modules can be called container runtimes or container engines now. containerd has been donated to [Cloud Native Computing Foundation](https://www.cncf.io), and runC to [Open Container Initiative](#open-container-initiative).

The company, CoreOS, and other leaders in the containerization established [Open Container Initiative](#open-container-initiative) in 2015. OCI provides standards around the containerization, but Docker Inc. contributes to the runtime specification part only.

### Container runtime vs container engine

[🔗](https://developers.redhat.com/blog/2018/02/22/container-terminology-practical-introduction) [🔗](https://www.docker.com/products/container-runtime/)

There are no clear definitions of **container runtime** and **container engine**. They are used interchangeably. It shouldn't be far from the truth that container runtimes can be divided into to two parts:

- [low-level container runtime](#container-runtime---low-level)
- [high-level container runtime](#container-runtime---high-level).

The **container engines** can be considered as a **high-level container runtimes**. They include such features like a user interface (like CLI or REST API) and handling of images. They often call **low-level container runtimes** to let them create and run containers. In such usage of the terms, **low-level container runtimes** are called just **container runtimes**.

![runtime-division](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uc0tg9ry7y6jefxbjo2c.png)

Red Hat is the example organization using terms like this, but Docker Inc.  mixes both terms within its [Docker Engine](https://docs.docker.com/engine/).

![docker-engine-runtime](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ks59f6952vv6cp9702.png)

It is not necessary that tools must implement all features destined for container runtimes. Some of tools implement only a part of features and interacts with other container runtime (e.g. dockerd and containerd).

> In this post I am going to use the **low-level container runtime** and **high-level container runtime** terms. In my opinion they are more accurate.

## Tool categories

### container runtime - low-level

[🔗](https://web.archive.org/web/20221206075452/https://www.ianlewis.org/en/container-runtimes-part-1-introduction-container-r)

Low-level container runtimes are responsible for managing **container** lifecycle. Nothing more. It means:

- creating, starting, stopping, and deleting **containers**
- setting up **namespaces**, **cgroups** and operating system security features (like **SELinux** policies and **AppArmor** rules) for containers
- consuming mounting points (**volumes**) prepared by [high-level container runtimes](#container-runtime---high-level)
- and then running commands inside those **namespaces** and **cgroups**.

Low-level runtimes abstract the OS primitives only, they are not designed to perform other tasks. They are mostly used by **high-level container runtimes**. You can interact with them directly, but it is not convenient.

Examples: [runC](https://github.com/opencontainers/runc), [crun](https://github.com/containers/crun), [LXC](https://linuxcontainers.org/).

### container runtime - high-level

[🔗](https://medium.com/tektutor/container-engine-vs-container-runtime-667a99042f3)

To fully derive benefits of containerization, it is not enough to just run containers. Their state and networking need to be managed and monitored. Containers are based on images, and images need to be managed. All of that needs to be done in a way that is easy to use and understand for developers, so the layer of interfaces needs to be provided as well.

Common container runtimes can co-work with [container orchestrators](#container-orchestrator), han handling individual **containers** runnings on every node in the cluster.

High-level container runtimes usually:

- rely on [low-level container runtimes](#container-runtime---low-level) to run **containers**
- set up networking between **containers**, so that they can communicate with each other, or the outside world
- handle inputs over CLI or API
- transport container **images** from/to a [registry](#registry-repository-tag) server
- prepare **volumes** for **containers**
- prepare metadata for **low-level container runtimes** (e.g., to overwrite `CMD`)
- monitor host **resources**

Examples of high-level container runtime: [containerd](https://containerd.io), [dockerd](https://www.docker.com/), [CRI-O](https://cri-o.io/), [LXD](https://linuxcontainers.org/lxd/), [Podman](https://podman.io/).

### container image build tool

[🔗](https://earthly.dev/blog/docker-vs-buildah-vs-kaniko/)

What runtimes can't do, by definition, is building container **images** (mostly from a Dockerfile). It is a job for container image build tools.

Container runtimes:

- may use separate modules (like dockerd using BuildKit, or Podman using Buildah)
- may not provide the the feature at all (like CRI-O and containerd).

Examples of image build tools: [BuildKit](https://docs.docker.com/build/buildkit/), [Buildah](https://buildah.io/), [kaniko](https://github.com/GoogleContainerTools/kaniko)

### container orchestrator

[🔗](https://developers.redhat.com/blog/2018/02/22/container-terminology-practical-introduction#container_orchestration)

A container orchestrator does two things:

- dynamically schedules container workloads within a cluster of computers
- provides a standardized application definition file (kube yaml, docker compose, etc.).

It allows containers within a cluster to be scheduled completely separately. Thanks to that it is easy to:

- deploy new instances of the same application into new environments
- scale up or down the number of instances of an application
- move an application from one environment to another.

On-premise examples: [Kubernetes](https://kubernetes.io/), [Docker Swarm](https://docs.docker.com/engine/swarm/).
Examples of cloud vendors' solutions: [Amazon ECS](https://aws.amazon.com/ecs/), [Azure Container Instances](https://azure.microsoft.com/en-us/services/container-instances/).

### daemon

> Sometimes, you can see a "daemon" term in the context of container runtimes.

The daemon, in general, is a long-running **process** that performs some tasks in the background. So some [container runtimes](#container-runtime---high-level), their modules, and tools around the containerization can be called like that due to their long-running nature.

The example tools called daemon: [dockerd](https://docs.docker.com/engine/reference/commandline/dockerd/), [containerd](https://containerd.io/), [LXD](https://linuxcontainers.org/lxd/), [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/).

In contrast to those, [Podman](https://podman.io/) is the daemonless container runtime.

## Standards

### Open Container Initiative

[🔗](https://opencontainers.org/)

[OCI](https://opencontainers.org/) is an open governance structure for the express purpose of creating open industry standards around container formats and runtimes. OCI specification is a set of standards for:

- [containers image format](#container-image-format) ([image-spec](#oci-image-format-specification-image-spec))
- [runtime](#container-runtime---low-level) ([runtime-spec](#oci-runtime-specification-runtime-spec))
- [distribution](#registry-repository-tag) ([distribution-spec](#oci-distribution-specification-distribution-spec)).

OCI develops [runC](https://github.com/opencontainers/runc) as well.

### OCI Image Format Specification (image-spec)

[🔗](https://github.com/opencontainers/image-spec/blob/main/spec.md)

The image-spec defines an **OCI Image**, consisting of an [image manifest](#image-manifest), an [image index](#image-index) (optional), a set of filesystem layers, and a [configuration](#oci-image-configuration). The goal of this specification is to enable the creation of interoperable tools for building, transporting, and preparing a container image to run.

### OCI Distribution Specification (distribution-spec)

[🔗](https://github.com/opencontainers/distribution-spec/blob/main/spec.md/)

[OCI](#open-container-initiative) distribution-spec defines an API protocol to facilitate and standardize the distribution of content. Container Registry supports pushing and pulling images complaint with [OCI image-spec](#oci-image-format-specification-image-spec). However, the distribution-spec is designed to be agnostic of content types.

### OCI Runtime Specification (runtime-spec)

[🔗](https://github.com/opencontainers/runtime-spec/blob/main/spec.md)

[OCI](#open-container-initiative) runtime-spec aims to specify the configuration, execution environment, and lifecycle of a **container** created from an [OCI Image](#oci-image-format-specification-image-spec).

A container's configuration is specified as the config.json for the supported platforms and details the fields that enable the creation of a container. The execution environment is specified to ensure that applications running inside a container have a consistent environment between runtimes along with common actions defined for the container's lifecycle.

### OCI Image Configuration

[🔗](https://github.com/opencontainers/image-spec/blob/main/config.md)

This specification outlines the JSON format describing [OCI images](#oci-image-format-specification-image-spec) for use with a [container runtime](#container-runtime---low-level) and its relationship to filesystem changesets, described in **layers**.

### container image format

[🔗](https://developers.redhat.com/blog/2018/02/22/container-terminology-practical-introduction#container_image_format)

[Container runtimes](#container-runtime---high-level) used to have their own container image formats. Docker images formats became the most popular standard. Over time, the industry has established a new standard - [OCI Image Format Specification](#oci-image-format-specification-image-spec), originally based on the [Docker Image Manifest V2, Schema 2](https://docs.docker.com/registry/spec/manifest-v2-2/).

### image manifest

[🔗](https://github.com/opencontainers/image-spec/blob/main/manifest.md)

The manifest is an [image format](#container-image-format) based JSON file that provides [configuration](#oci-image-configuration) and set of **layers** for a single **container image** for a specific architecture and operating system.

### image index

[🔗](https://github.com/opencontainers/image-spec/blob/main/image-index.md)

The image index is defined by [OCI](#open-container-initiative). It is a higher-level manifest which points to specific one or more [image manifests](#image-manifest), ideal for one or more platforms.

Docker supports [manifest list](https://docs.docker.com/registry/spec/manifest-v2-2/#manifest-list) instead of the image index.

### registry, repository, tag

The **registry** is the service to store and download (push/pull) container *images*. The information about the images is stored in the [manifest](#image-manifest) files.

Images inside the registry are grouped into **repositories**, and repositories can have subgroups such as organizations, projects, etc. A repository contains multiple **tags**. Each tag is a pointer to a specific image. The tag is usually a version number, but it can be any string. The default tag is `latest`. It is mutable (mutable) as opposed to blob sha256 (immutable).

```bash
docker run my-registry.com/some-/-organization/repository:tag
```

## Ending

The second part of the containerization journey behind us. You won't be confused anymore when you hear about runtime-related terms, like container runtime, Docker Engine, Podman, containerd, runC.

OCI is a new Docker now.

Now, knowing what is not the Docker, you must be eager to know what  actually is it. A part of a Docker tooling has been described here. Next time, I will expand upon the Docker environment. It is still significant part of the containerization world, so it desires for a separate post.