This document maybe INCORRECT
What is Docker?
Docker provides the ability to package and run an application in a loosely isolated environment called a container.
We can use Docker without considering the difference in OS.
Goal
- Understand what containers are
- Understand the architecture of Docker
especially, understand “container runtime” which is very important concept for Kubernetes
Linux containers (LXC)
What are Linux containers (LXC)?
Docker was initially built on top of Linux containers (LXC). It was created using cgroups and Linux namespaces.
There are two important concepts in LXC
-
Userspace: All the code which is required to run user programs (applications, process) is called userspace. When you initiate a program action, for example, to create a file, the process in the userspace makes a system call to Kernal space.
-
Kernel Space: This is the core of the OS, where you have the kernel code which interacts with the system hardware, storage, etc…
A container is a process actually and it is isolated in userspace (also from OS). In some cases, the process may have children processes (e.g. nginx, ref. https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/).
Also, as you may know, we can run multiple containers with the shared OS.
Concepts of LXC
Basically, containers are isolated in a host using the two Linux kernel features called namespaces and control groups.
- namespace → isolate processes
- cgroups → isolate resources (CPU, memory, network, etc…)
Docker
It is basically a container engine that uses the Linux Kernel features like namespaces and control groups to create containers on OS.
Core concepts of Docker
History of Docker
- Docker initially created based on LXC technology
- Docker moved from LXC to libcontainer in 2014
- runc is developed (a CLI for spinning up containers that follow all OCI specifications and it includes libcontainer) (OCI: Open Container Initiative is an open industry standard for container runtime and specifications).
- containerd (Docker separated its container management component to containerd in 2016)
Now, there are three main components
- Docker Engine (dockerd)
- docker-containerd (containerd)
- docker-runc (runc)
More precisely, Docker engine is composed of the docker daemon (dockerd), an API interface, and Docker CLI. The relationship between these components is
- daemon: It can create and manage docker images. Containers, networks, etc.
- API: It is used to instruct docker daemon what to do.
- CLI: It is a client which is used to enter docker commands (e.g. docker run …)
How do they work to run containers?
- Docker Engine (dockerd) calls API of docker-containerd based on the request from client (there is a specification called Container Runtime Interface, CRI)
- docker-containerd (containerd) manages images that can be used for running processes and asks runc to run processes
- docker-runc (runc) starts the process by using the images and orders about namespace, cgroups, etc…
Usually, components corresponding to containerd are called high-level container runtime and components corresponding to runc are called low-level container runtime.
Kubernetes supports several container runtime
References