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.
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).
- Table of contents
- Terminology schema
- Docker legacy
- Tool categories
I prepared the next map 🗺️ with relations between terms for you. With it, we can continue our journey.
[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.
A little historical overview is needed to fairly learn containerization tools and to finally answer the question "why is everything called Docker?".
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, containerd, 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, and runC to Open Container Initiative.
The company, CoreOS, and other leaders in the containerization established Open Container Initiative in 2015. OCI provides standards around the containerization, but Docker Inc. contributes to the runtime specification part only.
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:
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.
Red Hat is the example organization using terms like this, but Docker Inc. mixes both terms within its Docker Engine.
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.
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
- 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.
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, han handling individual containers runnings on every node in the cluster.
High-level container runtimes usually:
- rely on low-level container runtimes 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 server
- prepare volumes for containers
- prepare metadata for low-level container runtimes (e.g., to overwrite
- monitor host resources
What runtimes can't do, by definition, is building container images (mostly from a Dockerfile). It is a job for container image build tools.
- 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).
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.
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, their modules, and tools around the containerization can be called like that due to their long-running nature.
In contrast to those, Podman is the daemonless container runtime.
OCI 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:
OCI develops runC as well.
The image-spec defines an OCI Image, consisting of an image manifest, an image index (optional), a set of filesystem layers, and a 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-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. However, the distribution-spec is designed to be agnostic of content types.
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.
Container runtimes 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, originally based on the Docker Image Manifest V2, Schema 2.
Docker supports manifest list instead of the image index.
The registry is the service to store and download (push/pull) container images. The information about the images is stored in the 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).
docker run my-registry.com/some-/-organization/repository:tag
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.