Что странного в Docker: контейнеры, не VM, а образы, папки
22 октября 2026 года на codeandcake.dev вышла заметка «Docker is weird». Автор пишет, что решил ради интереса сделать собственный контейнерный рантайм (программу, запускающую контейнеры), и хотя находится ещё в самом начале пути, уже узнал о Docker немало странного. Имя автора в тексте не указано.
Первое: контейнеры «не настоящие». В отличие от виртуальных машин, это просто процессы с особыми ограничениями, и этот процесс по-прежнему исполняет ядро хоста; при желании его можно найти в /proc. Более того, в Linux нет отдельной функции «контейнеры»: по словам автора, это пять разных возможностей ядра Linux, «надетых друг на друга в одном плаще». Пространства имён (namespaces) скрывают от хоста и контейнера то, что им видеть не нужно, cgroups ограничивают потребление ресурсов, а за изоляцию сети отвечает «куча сетевой магии», которую автор признаётся не понимать.
Второе: образы, это просто папки. Docker кладёт папку в некое место и вызывает chroot (или pivot_root), чтобы сделать её корневым каталогом процесса контейнера. Поэтому команда docker run -it --rm ubuntu /bin/bash означает: скачать образ ubuntu из Dockerhub, положить его куда-то и запустить bash по какому-то странному пути внутри каталога Docker.
Третье: по мнению автора, Go, довольно неудачный язык для контейнерного рантайма. Рантайм Docker, runc, написан на Go, а среда выполнения Go изначально многопоточная. Многие системные вызовы Linux, нужные контейнерному рантайму, должны выполняться в однопоточной среде, поэтому в runc есть «безумный» модуль на C, который запускается до инициализации среды выполнения Go. Кроме того, в Go нет fork: он копирует только главный поток, что в такой среде похоже на ловушку. А рантайму нужно сделать fork, наложить ограничения и затем запустить процесс из docker run. Чтобы обойти это, runc запускает /proc/self/exe со специальным аргументом командной строки, по которому процесс понимает, что он дочерний, и так приближённо имитирует fork.
Четвёртое: Docker требует root. Это легко упустить, если, как автор, запускать Docker на MacOS. Многие API ядра Linux, которыми пользуются рантаймы, требуют (или раньше требовали) прав root, поэтому демон Docker обычно работает от root. Автор добавляет, что представляет, как непроста работа по безопасности контейнеров. Сегодня ситуация, по его словам, вроде бы лучше, главное исключение, сеть: рантайму без root, судя по всему, приходится заново реализовывать весь сетевой стек в пользовательском пространстве, чтобы дать те же возможности.
Итог автора: он только начал свой рантайм, но уже многое понял о Docker, и написание собственной версии инструмента, которым пользуешься, отличный способ его изучить.
Ключевые факты
- Контейнер, по описанию автора, это обычный процесс с ограничениями, который исполняет ядро хоста и который можно найти в /proc; от виртуальных машин он отличается принципиально.
- Отдельной функции «контейнеры» в Linux нет: автор называет их пятью разными возможностями ядра в одном плаще, пространства имён, cgroups и сетевая изоляция в их числе.
- Образ, просто папка, которую Docker кладёт на диск и делает корневым каталогом процесса через chroot или pivot_root.
- В runc (на Go) нужен модуль на C до старта среды выполнения Go и запуск /proc/self/exe вместо fork, из-за многопоточности Go.
- Демон Docker обычно работает от root, а режим без root, по словам автора, стал лучше, но сеть остаётся главной сложностью.
Почему это важно
Docker стал привычным инструментом разработки, но мало кто представляет, что стоит за командой docker run. Заметка простыми словами показывает: контейнер, не маленькая виртуальная машина, а процесс на ядре хоста с ограничениями, а образ, каталог, подменяющий корень файловой системы. Это объясняет, почему безопасность контейнеров, отдельная серьёзная тема. Новых продуктов или исследований в тексте нет, это личный разбор человека, изучающего устройство Docker на практике.
Кому это важно
Разработчикам и DevOps-инженерам, которые пользуются Docker, но не знают его внутренностей; тем, кто думает написать собственный контейнерный рантайм или хочет понять, чем контейнеры отличаются от виртуальных машин; тем, кого интересуют вопросы безопасности контейнеров и работы без root.
Как это применить
Прямых инструкций в заметке нет. Практический вывод автора: чтобы лучше понять инструмент, которым пользуешься, напишите свою версию. Для более скромной проверки можно найти процесс контейнера в /proc на Linux-хосте или посмотреть, как docker run раскладывает образ по файловой системе. Платных тарифов или лицензий в тексте не упоминается.
Можно ли доверять
Это неформальный личный блог без указанного имени автора. Автор сам пишет, что находится на раннем этапе своего проекта и чего-то не понимает (например, сетевую изоляцию). Цифр, замеров и версий в тексте нет. Оценки вроде «Go, неудачный язык для рантайма», мнение автора, а не установленный факт. Реакций разработчиков Docker или runc в источнике нет.
Риски и подводные камни
Заметка упрощает картину: она не перечисляет все пять функций ядра полностью и не претендует на полноту. Утверждения о режиме без root сформулированы с оговорками («кажется», «похоже»), поэтому не стоит принимать их за точное описание современных рантаймов. Если запускать Docker на MacOS, требование root легко упустить, и это нужно учитывать при оценке безопасности.
«Контейнеры, это на самом деле пять разных функций ядра Linux в одном плаще.»
— автор заметки «Docker is weird», codeandcake.dev