← Назад к вопросам

На чём строится изоляция докера

2.0 Middle🔥 181 комментариев
#Docker и контейнеризация#Linux и администрирование

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Архитектура изоляции в Docker: на чём она строится

Изоляция в Docker — это не единая технология, а многоуровневая комбинация механизмов операционной системы Linux (или Windows), которые совместно создают "лёгкие" контейнеры. В отличие от виртуальных машин с аппаратной виртуализацией, контейнеры делят ядро хоста, что делает их значительно более эффективными по ресурсам и скорости запуска.

Ключевые технологии-основы

1. Пространства имён (Linux Namespaces)

Это фундаментальный механизм ядра Linux для изоляции и виртуализации системных ресурсов. Каждый контейнер получает свой собственный набор пространств имён, что создаёт иллюзию выделенной ОС. Основные типы:

  • PID (Process): Изолирует дерево процессов. Процессы в контейнере видят только свои PID, начинающиеся с 1 (init процесса контейнера). На хосте они имеют обычные PID.
  • Network (net): Предоставляет контейнеру собственный стек сетевых интерфейсов, таблицы маршрутизации, правила iptables/nftables. Это основа для сетевых драйверов Docker (bridge, host, overlay).
  • Mount (mnt): Изолирует точки монтирования файловой системы. Контейнер видит собственный корень (/) и не имеет доступа к смонтированным на хосте файлам, если это явно не разрешено.
  • UTS (Unix Time Sharing): Позволяет контейнеру иметь собственное имя хоста (hostname) и домена (domainname), независимое от хостового.
  • IPC (Inter-Process Communication): Изолирует механизмы межпроцессного взаимодействия (очереди сообщений, сегменты разделяемой памяти, семафоры).
  • User (user): Отделяет таблицу идентификаторов пользователей и групп. Позволяет отображать root внутри контейнера в непривилегированного пользователя на хосте (техника rootless containers), значительно повышая безопасность.

Эти пространства создаются при старте контейнера. Наглядно разницу PID namespace можно увидеть так:

# Запускаем контейнер с изолированным процессом sleep
docker run -d --name test-isolation alpine sleep 3600

# Смотрим процессы ВНУТРИ контейнера (его PID namespace)
docker exec test-isolation ps aux
# Будет виден процесс sleep с PID=1 (или близким к 1)

# Смотрим процессы СНАРУЖИ, на хосте (глобальный PID namespace)
ps aux | grep sleep
# Будет виден процесс с обычным, большим PID (например, 12345)

2. Группы управления ресурсами (Control Groups - cgroups)

Если пространства имён отделяют ресурсы, то cgroups их ограничивают и учливают. Это механизм ядра для ограничения, учёта и изоляции потребления ресурсов (CPU, память, диск I/O, сеть) группой процессов.

  • Ограничение (limiting): Задаёт жёсткие лимиты. Например, контейнер не сможет использовать более 512 МБ RAM.
  • Приоритезация (prioritization): Распределяет ресурсы между контейнерами. Например, гарантирует 50% CPU time или устанавливает веса (cpu.shares).
  • Учёт (accounting): Измеряет потребление ресурсов, что используется для мониторинга и биллинга.
  • Управление (control): Позволяет заморозить (freeze), перезапустить или завершить группу процессов.

Пример файловой иерархии cgroup v2 для ограничения памяти контейнера:

# Docker автоматически создаёт cgroup для каждого контейнера
# Путь обычно: /sys/fs/cgroup/<подсистема>/docker/<container-id>/

# Чтение текущего использования памяти контейнера
cat /sys/fs/cgroup/memory/docker/<container-id>/memory.usage_in_bytes

# Установка лимита памяти (это делает Docker Engine через API runc)
echo "536870912" > /sys/fs/cgroup/memory/docker/<container-id>/memory.limit_in_bytes # 512 МБ

3. Объединённая файловая система (Union File System)

Она обеспечивает изоляцию на уровне файлов. Основные принципы:

  • Слои (Layers): Каждая инструкция в Dockerfile (RUN, COPY, ADD) создаёт неизменяемый слой. Контейнер — это тонкий записываемый слой поверх этих слоёв-образов.
  • Copy-on-Write (CoW): Все слои доступны только для чтения. При попытке модификации файла из нижнего слоя, система копирует его в верхний, записываемый слой контейнера. Это обеспечивает эффективное использование диска и быстрый запуск множества контейнеров от одного базового образа.
  • Драйверы хранения: Docker использует плагинируемые драйверы (overlay2 (рекомендуемый), aufs, devicemapper, zfs), которые реализуют UnionFS на практике.

Сборка "пазла": как Docker это использует

Docker Engine выступает как высокоуровневый оркестратор этих низкоуровневых механизмов. Последовательность при запуске контейнера примерно такова:

  1. CLI передаёт команду docker run Docker Daemon.
  2. Daemon подготавливает образ (UnionFS слои) и запрашивает создание контейнера у runc (реализация OCI Runtime Specification).
  3. runc вызывает системный вызов clone() (или unshare()) с флагами CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWNS | ..., создавая новое пространство имён.
  4. Процесс помещается в новую cgroup, где для него устанавливаются заданные лимиты ресурсов.
  5. Монтируется корневая файловая система контейнера с использованием драйвера UnionFS (overlay2).
  6. Запускается процесс-точка входа (например, /bin/bash), который уже работает в полностью изолированном окружении.

Важные нюансы и эволюция

  • Неполная изоляция: Контейнеры делят ядро хоста. Уязвимость в ядре может скомпрометировать все контейнеры, в отличие от ВМ. Критически важные приложения могут требовать дополнительной изоляции через Kata Containers, gVisor или аппаратные ВМ.
  • Безопасность: Базовые пространства имён и cgroups — не silver bullet. Для усиления безопасности применяются профили Seccomp (фильтрация системных вызовов), AppArmor/SELinux (Мандатный контроль доступа), Capabilities (дробление привилегий root) и Rootless-режим.
  • cgroups v2: Современные дистрибутивы переходят на cgroups v2, который предлагает единую иерархию, улучшенное управление ресурсами (особенно для CPU и I/O) и лучшую безопасность. Docker и Kubernetes уже полностью поддерживают v2.

Итог: Изоляция Docker строится на мощном фундаменте ядра Linux: пространствах имён для виртуализации представления о системе, cgroups для контроля ресурсов и UnionFS для эффективного управления файлами. Docker (через containerd и runc) грамотно оркестрирует эти механизмы, предоставляя простой API для создания переносимых, плотно упакованных и достаточно изолированных единиц развёртывания — контейнеров.