Краткая история и OCI
Идея «изолировать процесс» в Unix-мире намного старше, чем Docker. Docker появился в 2013 году и стал популярен не потому, что изобрёл изоляцию, а потому что упаковал её в удобный CLI с понятным форматом образов. Чтобы понять текущую экосистему — где Docker, где containerd, где OCI, где Podman — нужно пройти по таймлайну.
Этот урок короче предыдущего, и в нём больше дат и имён. Цель — чтобы ты на собеседовании или в чате с коллегой понимал, о чём речь, когда слышишь «containerd», «runc», «OCI image spec» или «cri-o».
Таймлайн
chroot (1979) — старший родственник
chroot появился ещё в Unix V7. Это очень простая штука: процессу меняется видимый корень файловой системы.
Mount, /etc/fstab и mount namespaces Был /, стал /some/subdir. Теперь процесс физически не может выйти за пределы этой папки (через корень — может через другие лазейки, об этом ниже).
chroot до сих пор используется для:
- Сборки пакетов в чистой среде.
- Восстановления Linux-системы из live-CD.
- Простых «sandbox» для устаревших приложений.
Что chroot не делает: ничего не изолирует, кроме видимости файловой системы. Процесс видит все PID, все сети, все IPC. На современном Linux простой chroot — это игрушка, а не изоляция.
FreeBSD jails (2000) и Solaris Zones (2004)
Эти два инструмента были первыми «настоящими» контейнерами в Unix-мире. Они изолировали не только корень FS, но и:
- Сеть (свой стек или свой IP).
- Процессы (свой list).
- Пользователей.
FreeBSD jails до сих пор живёт и используется в FreeBSD-продакшенах. Solaris Zones живёт в illumos-дистрибутивах (SmartOS, OmniOS).
На Linux в это время ничего сопоставимого не было. Только хаки на chroot и редкие проекты вроде Linux-VServer и OpenVZ.
cgroups + namespaces (2006-2008) — два кирпича Docker
В 2006-2008 годах в Linux kernel добавили две вещи, без которых Docker был бы невозможен:
- cgroups — изначально проект Google для управления ресурсами на их фермах (Borg).
- namespaces — инкрементально добавлялись разные типы. Mount namespace (2002), UTS (2006), IPC (2006), PID (2008), Network (2008), User (2013), и т.д.
К 2011 году все базовые namespace типы были в mainline kernel. Это и есть тот момент, когда «можно делать контейнеры на Linux».
LXC (2008) — первый Linux container
LXC (Linux Containers) — это набор userspace утилит, которые используют cgroups + namespaces, чтобы запустить полную Linux-систему в контейнере. Не один процесс, а целый дистрибутив.
LXC рабочий, но сложный — конфиг тяжёлый, нет красивого CLI, нет образов в том смысле, в каком они появились в Docker. До сих пор используется в LXD (Canonical), и для системных контейнеров (где нужен полноценный init и набор сервисов).
Docker (2013) — то, что взлетело
Solomon Hykes показал прототип Docker на PyCon 2013. Изначально Docker использовал LXC под капотом, но скоро переписал свой runtime (libcontainer, позже выделенный в runc).
Что сделало Docker популярным:
- Image формат. Слои, кеширование, тэги. До этого «образ» — это просто tarball. Docker сделал слоистый формат, который позволяет переиспользовать общие куски.
- Docker Hub. Публичный registry, где
docker pull nginxработало за пять секунд, и тебе не надо было ничего настраивать. Это был сетевой эффект — все начали публиковать образы. - Простой CLI.
docker run,docker build,docker push. Одна команда — один результат. - Dockerfile. Декларативный формат для сборки образа. Намного проще, чем bash-скрипты сборки.
К 2015 году Docker стал стандартом де-факто для контейнеризации.
OCI (2015) — стандарт, чтобы не быть запертыми
К 2015 году стало понятно: Docker — компания, она может развернуться куда угодно. Индустрии нужен открытый стандарт, чтобы не быть зависимыми от одной реализации. Так появился Open Container Initiative (OCI) — консорциум под крылом Linux Foundation.
OCI стандартизировал две вещи:
- OCI Image Format — формат, в котором лежит образ (манифест, слои, конфиг).
- OCI Runtime Spec — как должен выглядеть runtime, который запускает контейнер из распакованного образа.
Docker отдал свой runtime (runc) и формат image в OCI. Теперь любая реализация может быть OCI-совместимой: containerd, CRI-O, Podman, gVisor, Kata Containers.
Что такое syscall — физический переход из userspace в kernel
Картина после 2017: «докер» больше не одно
Когда ты пишешь docker run nginx, на самом деле работает целая цепочка:
- docker (CLI) шлёт HTTP-запрос на
/var/run/docker.sockк dockerd. - dockerd просит containerd создать контейнер.
- containerd через containerd-shim запускает runc.
- runc делает
clone()с правильными флагами, монтирует rootfs, применяет cgroups, иexec()-ит главный процесс.
Kubernetes пропускает первые два шага — он работает напрямую с containerd (через CRI — Container Runtime Interface). Поэтому в k8s-кластере docker daemon не нужен, нужен только containerd или CRI-O.
Альтернативы Docker сегодня (2026)
- Podman (Red Hat) — daemonless, rootless по умолчанию. Не нужен root для запуска контейнеров. Совместим с Docker CLI:
alias docker=podmanчасто работает. - containerd + nerdctl — то же containerd, что внутри Docker, но с прямым CLI.
- OrbStack (mac only) — Docker-совместимый рантайм для macOS, который стартует за секунды и потребляет меньше памяти.
- Rancher Desktop — Docker + k3s в одном пакете, open source.
- Colima — CLI-only альтернатива Docker Desktop для mac на базе lima (Linux VM).
Все они OCI-совместимы. Образ, собранный через docker build, можно запустить через podman run или nerdctl run — это и есть смысл стандартизации.
Попробуй сам
Если у тебя установлен Docker, посмотри на цепочку процессов:
docker run -d --name demo nginx
ps -ef | grep -E '(dockerd|containerd|runc)' | grep -v grep
Ты увидишь dockerd, containerd, и containerd-shim-runc-v2. Это и есть многослойный стек. Сам процесс nginx будет дочерним от shim’а.
Останови контейнер:
docker rm -f demo
На macOS с OrbStack или Docker Desktop вся эта цепочка крутится в Linux-VM, поэтому ps -ef на хосте покажет только сам клиент. Но внутри VM (доступ через docker run --rm --privileged -it alpine sh + ps) — стек тот же.