OCI, containerd, Podman: что под капотом Docker

↑ Этап 2 · Контейнеры: Docker, docker-compose, Makefile

Обязательно~4 мин чтенияУровень: junior

Зачем это на собесе

Docker — лишь один из инструментов. Понимание стека (OCI, containerd, runc) нужно для Kubernetes и отладки.

Стандарты OCI

Open Container Initiative (Linux Foundation) задаёт открытые стандарты:

  • Image Spec: формат образа (манифест, конфигурация, слои, контент-адресация по sha256);
  • Runtime Spec: как запускать контейнер по «бандлу» (config.json + rootfs);
  • Distribution Spec: API реестров образов (/v2/..., pull/push).

Благодаря стандартам образ, собранный Docker, запускается в Podman, containerd, CRI-O и Kubernetes.

Стек компонентов

docker CLI ──▶ dockerd (Docker Engine, API, сети, тома, build)
                  │
                  ▼
              containerd (управление жизненным циклом, образы, снимки)
                  │
                  ▼
              containerd-shim ──▶ runc ──▶ процесс контейнера (namespaces, cgroups)
КомпонентРоль
runcнизкоуровневый runtime (референсная реализация OCI): создаёт namespaces/cgroups и запускает процесс
containerdвысокоуровневый runtime: загрузка образов, хранилище, снимки, вызовы runc; используется Docker и Kubernetes
dockerdдемон Docker: REST API, build (BuildKit), сети, volumes, compose
containerd-shim«прокладка»: контейнер не зависит от перезапуска containerd; хранит stdio/код выхода
CRI-Oлёгкий runtime специально для Kubernetes
crun, youki, gVisor (runsc), kataальтернативные низкоуровневые runtimes
nerdctlDocker-совместимый CLI для containerd
ctr, crictlнизкоуровневые CLI (отладка containerd / CRI)

Kubernetes и Docker

CRI (Container Runtime Interface) — API между kubelet и runtime. С версии 1.24 Kubernetes убрал dockershim: кластеры используют containerd или CRI-O напрямую. Образы Docker по-прежнему работают (стандарт OCI). Для отладки на ноде: crictl ps, crictl logs, crictl images.

Podman

Совместимая с Docker CLI альтернатива без демона и с упором на rootless.

podman run -d --name web -p 8080:80 nginx
podman ps; podman logs web; podman build -t app .
podman generate kube web > web.yaml      # генерация манифеста Kubernetes
podman play kube web.yaml                # запуск pod из YAML
podman pod create --name mypod -p 8080:80   # поды как в Kubernetes
podman compose up                        # или podman-compose

Особенности:

  • без демона (fork/exec, каждый контейнер — дочерний процесс пользователя): нет единой точки отказа и root-демона;
  • rootless по умолчанию: контейнеры без root-привилегий на хосте (user namespaces, slirp4netns/pasta для сети);
  • интеграция с systemd (Quadlet: .container unit-файлы) — запуск контейнеров как сервисов;
  • alias docker=podman для совместимости; Buildah (сборка), Skopeo (копирование образов между реестрами).

Образ внутри

docker save nginx -o nginx.tar && tar -tf nginx.tar      # манифест, конфиг, слои (tar)
skopeo inspect docker://nginx:1.27
crane manifest nginx:1.27 | jq                            # go-containerregistry

Манифест → конфиг (env, cmd, entrypoint) + список слоёв; digest (sha256:...) идентифицирует контент неизменяемо, теги — подвижные указатели.

Сборка

BuildKit (по умолчанию в Docker): параллельная сборка, кэш, секреты (--mount=type=secret), SSH, multi-platform (buildx). Альтернативы: Buildah, Kaniko (без демона, для CI в Kubernetes), ko (Go), Jib (Java), dotnet publish /t:PublishContainer (.NET без Dockerfile).

Вопросы с ответами