Контейнеризация

Материал из llmdocs — справочник разработчика
Контейнеризация
Принципизоляция процессов на общем ядре ОС
Механизмы Linuxnamespaces, cgroups, capabilities, seccomp, overlay-файловые системы
Предшественникиchroot (1979), FreeBSD jails (2000), Solaris Zones (2004), LXC (2008)
Массовое распространениеDocker (2013)
СтандартOpen Container Initiative (OCI, с 2015)
ОркестрацияKubernetes, Docker Swarm, Nomad
ИнструментыDocker, Podman, containerd, CRI-O

Контейнеризация — способ упаковать приложение вместе с его зависимостями (библиотеками, интерпретатором, конфигурацией) в контейнер — изолированную среду, которая одинаково запускается на ноутбуке разработчика, тестовом сервере и в облаке. В отличие от виртуальной машины, контейнер не содержит собственного ядра операционной системы: все контейнеры на хосте используют общее ядро, а изоляция обеспечивается его механизмами. Поэтому контейнеры запускаются за доли секунды и расходуют мало ресурсов.

Контейнеры — основа современной разработки и эксплуатации: приложения поставляются как образы Docker, собираются по Dockerfile, запускаются локально через Docker Compose и в продакшене — под управлением Kubernetes.

Зачем нужны контейнеры

  • «У меня работает». Образ содержит всё нужное приложению, поэтому разница между средами разработки и продакшена исчезает.
  • Изоляция зависимостей. На одном сервере уживаются сервисы с несовместимыми версиями Python, библиотек и системных пакетов.
  • Плотность и скорость. Десятки контейнеров на одном сервере вместо нескольких виртуальных машин; запуск — за секунды.
  • Неизменяемость. Образ собирается один раз и разворачивается без изменений; обновление — это замена контейнера новым, а откат — запуск предыдущей версии образа.
  • Единый формат поставки для CI/CD, облаков и оркестраторов.[4]

Контейнеры и виртуальные машины

Виртуальная машина Контейнер
Что виртуализируется оборудование окружение процесса
Ядро ОС своё в каждой ВМ общее с хостом
Размер образа гигабайты мегабайты — сотни мегабайт
Запуск десятки секунд — минуты доли секунды
Изоляция сильная (гипервизор) слабее (общее ядро)
Другая ОС любая только совместимая с ядром хоста

Контейнер Linux нельзя напрямую запустить на ядре Windows или macOS — Docker Desktop на этих системах тайно запускает небольшую виртуальную машину с Linux. Если нужна более сильная изоляция, используют гибриды: gVisor перехватывает системные вызовы, а Kata Containers и Firecracker запускают каждый контейнер в лёгкой виртуальной машине.

Как устроен контейнер в Linux

Контейнер — это обычный процесс, на который ядро наложило ограничения (см. Namespaces и cgroups):

  • Namespaces (пространства имён) ограничивают то, что процесс видит: собственное дерево процессов (PID), сетевые интерфейсы (net), точки монтирования (mnt), имя хоста (UTS), пользователей (user), IPC.[1]
  • Cgroups (контрольные группы) ограничивают то, сколько процесс потребляет: память, процессор, ввод-вывод, число процессов.[2]
  • Capabilities, seccomp, AppArmor/SELinux урезают привилегии: даже root внутри контейнера не может загружать модули ядра или менять системное время (см. Права доступа в Unix).
  • Многослойная файловая система (overlayfs) собирает корневую ФС контейнера из слоёв образа, доступных только для чтения, и тонкого слоя для записи.
docker run --rm -it --memory 256m --cpus 0.5 alpine sh
# внутри: ps aux покажет только процессы контейнера, hostname — свой

История

Идея изоляции появилась задолго до Docker. Системный вызов chroot (Unix V7, 1979) подменял корневой каталог процесса. В 2000 году FreeBSD добавила jails — изолированные окружения с собственными пользователями и сетью,[5] в 2004 году Sun представила Solaris Zones. В Linux механизмы появлялись постепенно: namespaces с 2002 года, cgroups — разработка инженеров Google, вошедшая в ядро в 2008 году. В том же году появился LXC, собравший их в удобный инструмент.

Прорывом стал Docker (2013): он добавил простой формат образов со слоями, Dockerfile и публичный реестр Docker Hub, превратив контейнеры из инструмента администраторов в инструмент разработчиков. В 2014 году Google открыла Kubernetes, а в 2015 году индустрия создала Open Container Initiative (OCI), которая стандартизировала формат образов и среды выполнения, чтобы контейнеры не зависели от одного поставщика.[3]

Экосистема

Слой Что делает Примеры
Сборка образ по описанию Docker Build (BuildKit), Buildah, kaniko
Хранение реестр образов Docker Hub, GitHub Container Registry, Harbor (см. Container registry)
Запуск низкого уровня создаёт процесс с namespaces и cgroups runc, crun
Среда выполнения управляет образами и контейнерами containerd, CRI-O
Инструменты разработчика CLI и локальная работа Docker, Podman, nerdctl
Оркестрация кластер, масштабирование, самовосстановление Kubernetes, Nomad, Docker Swarm

Формат описан в статье Образ контейнера и OCI. Kubernetes с 2022 года работает с containerd или CRI-O напрямую, без Docker, но образы, собранные Docker, остаются совместимыми благодаря OCI.[6]

Хорошие практики

  • Один процесс (одна ответственность) на контейнер; логи — в стандартный вывод.
  • Минимальные базовые образы (alpine, distroless, -slim) и многоэтапная сборка — меньше размер и поверхность атаки.
  • Запуск не от root, файловая система только для чтения, где возможно.
  • Никаких секретов внутри образа: их передают через переменные окружения или хранилища секретов.
  • Состояние — в томах или внешних сервисах; сам контейнер можно в любой момент удалить и пересоздать.

См. также

Источники

  1. namespaces(7) — Linux manual page
  2. Linux kernel documentation — Control Group v2
  3. Open Container Initiative — About
  4. Docker Docs — What is a container?
  5. FreeBSD Handbook — Jails
  6. Kubernetes Documentation — Containers