Сегодня контейнеры стали стандартом: Docker, Podman, Kubernetes — знакомые слова даже для новичков. Но за всей этой экосистемой стоит довольно простая идея: Linux уже давно умеет изолировать окружения без сторонних тулов. Иван Величко в своей статье показывает, как собрать контейнер «на коленке» всего с тремя инструментами — unshare, mount и pivot_root.
🧩 Сердце контейнера — mount namespace
- 🗂 Mount namespace изолирует таблицу монтировок: процессы в контейнере видят свою файловую иерархию.
- 🔒 Для настоящей изоляции нужно установить propagation в private, иначе изменения могут «просачиваться» обратно на хост.
- 📜 Проверить пространство имён легко: readlink /proc/$PID/ns/mnt — разные inode = разные namespace.
Интересно, что mount namespaces появились ещё в Linux 2.4 (2002 год), задолго до появления Docker.
🛠 Построение контейнера с нуля
- 📦 Rootfs — берём готовый образ (например, Alpine) и распаковываем в отдельную директорию.
- 🌀 Создаём namespace: unshare --mount открывает новую таблицу монтировок.
- 🔄 Меняем корень через pivot_root на наш rootfs. Это безопаснее chroot, так как старый корень изолируется в .oldroot и потом отмонтируется.
- ⚙️ Монтируем виртуальные файловые системы: /proc, /dev, /sys. Без этого ps или df не заработают.
- 🛡 Хардним окружение: делаем часть /proc read-only, маскируем чувствительные узлы (/proc/kcore, /sys/firmware и т. д.).
- 🧩 Заменяем спецфайлы /etc/hosts, /etc/hostname, /etc/resolv.conf на уникальные для контейнера.
В итоге получаем «чистую» среду с отдельным rootfs и минимальной утечкой в хостовую систему.
💡 Моё мнение
Мне особенно понравилось, что вся эта «магия Docker» сводится к старым, надёжным системным вызовам. Это напоминает, что контейнеры — не чёрный ящик, а сборка из стандартных возможностей ядра.
Для инженеров понимание механики важно не только ради любопытства. Когда Kubernetes «глючит» с volume, или Docker ведёт себя странно с bind mounts, знание про propagation (rprivate, rshared) позволяет быстро найти и устранить проблему.
И ещё один вывод: контейнеры — это не про «волшебные overlayfs». Можно построить полноценный runtime и без них. Overlay лишь экономит место за счёт слоёв, но ядро Linux и без него прекрасно умеет работать с rootfs.
✨ Вывод: контейнер — это всего лишь процесс с другим rootfs и набором пространств имён. Понимая это, проще перестать воспринимать Docker как магию и начать использовать Linux осознанно.
📚 Источники:
- man-страницы: namespaces(7), mount_namespaces(7), pivot_root(2)