Итак, Docker - это несколько технологий по созданию, транспортировке, запуску и управлению контейнерами. Давай попробуем собрать это всё воедино.

Когда мы запускаем с помощью Docker CLI команду для создания контейнера

docker container run -it ubuntu

, то клиент Docker преобразует команду в запрос к restful API, который затем передает её демону dockerd.

Демон Docker, получив инструкцию, сначала проверяет, доступен ли предоставленный образ в локальной системе. Если это не так, образ загружается из docker-реджистри (по умолчанию Docker Hub).

Как только образ получен, будет вызван containerd, чтобы запустить контейнер. containerd отвечает за преобразование загруженного образа в специальный bundle. Это такой набор файлов, который соответствует спецификации OCI.

Затем он передает пакет в обёртку containerd-shim, которая, в свою очередь, вызывает среду runC, которая и запускает контейнер.

runC взаимодействует с механизмами namespaces и cgroups в ядре, и они производят изоляцию некоторой вычислительной части нашего хоста, которая и есть контейнер. Вот именно так создаётся контейнер, если мы используем для запуска Docker.