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

На основе каких примитивов ядра работает Docker

3.0 Senior🔥 62 комментариев
#Docker и контейнеризация

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

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

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

Основные примитивы ядра Linux, лежащие в основе Docker

Docker, как платформа контейнеризации, базируется на комбинации нескольких ключевых примитивов ядра Linux, которые обеспечивают изоляцию, управление ресурсами и безопасность контейнеров. Эти примитивы позволяют запускать изолированные пользовательские пространства (user spaces), которые разделяют одно и то же ядро операционной системы.

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

Это фундаментальный механизм изоляции, который позволяет разделить глобальные системные ресурсы так, чтобы процессы в одном namespace видели только свои собственные ресурсы. Docker использует несколько типов namespaces:

  • PID namespace: Изолирует идентификаторы процессов. Процессы внутри контейнера начинаются с PID 1, не видя процессы хоста или других контейнеров.

    # Пример: создание нового PID namespace
    sudo unshare --pid --fork --mount-proc /bin/bash
    # В новом shell'е ps aux покажет только процессы этого namespace
    
  • Network namespace: Изолирует сетевые стеки (интерфейсы, таблицы маршрутизации, iptables правила). Каждый контейнер получает свой собственный виртуальный сетевой интерфейс и loopback.

    # Создание и настройка network namespace
    sudo ip netns add mynetns
    sudo ip netns exec mynetns ip link list
    
  • Mount namespace: Изолирует точки монтирования файловой системы. Позволяет контейнеру иметь собственное дерево каталогов, независимое от хоста.

  • UTS namespace: Изолирует системные идентификаторы hostname и domainname. Контейнер может иметь собственное сетевое имя.

  • IPC namespace: Изолирует ресурсы межпроцессного взаимодействия (очереди сообщений, сегменты разделяемой памяти, семафоры).

  • User namespace: Изолирует пространства идентификаторов пользователей и групп (UID, GID). Позволяет отображать root внутри контейнера в непривилегированного пользователя на хосте, повышая безопасность.

2. Control Groups (cgroups)

В то время как namespaces обеспечивают изоляцию, cgroups отвечают за учёт и ограничение ресурсов. Они позволяют Docker контролировать и ограничивать ресурсы, потребляемые контейнерами, предотвращая ситуации, когда один контейнер монополизирует ресурсы хоста.

  • Ограничение ресурсов:
    *   **CPU**: Ограничение доли процессорного времени (через `cpu.shares`) или установка лимитов в ядрах/миллиардах (cpuset, cpu.cfs_quota_us).
    *   **Память**: Установка жестких лимитов (`memory.limit_in_bytes`) и контроль за свопом.
    *   **Дисковый I/O**: Ограничение пропускной способности чтения/записи для блочных устройств.
    *   **Сеть**: Ограничение пропускной способности сети (часто через **TC** — Traffic Control).

```bash
# Пример: просмотр cgroup контейнера для ограничения памяти
# Найдите cgroup контейнера (например, в /sys/fs/cgroup/memory/docker/<container-id>/)
cat /sys/fs/cgroup/memory/docker/<container-id>/memory.limit_in_bytes
```

3. Union File Systems (UnionFS) и Copy-on-Write (CoW)

Эти технологии лежат в основе эффективного хранения и управления образами контейнеров.

  • UnionFS (Overlay2, AUFS, devicemapper, btrfs, zfs): Объединяет несколько слоёв файловой системы в единое представление. Образ Docker состоит из серии read-only слоёв, а контейнер добавляет поверх них тонкий read-write слой.

  • Copy-on-Write (CoW): Механизм, при котором данные копируются только при модификации. Это обеспечивает:

    *   **Эффективность дискового пространства**: Все контейнеры на основе одного базового образа (например, `ubuntu:latest`) разделяют общие read-only слои.
    *   **Быстрый запуск контейнеров**: Не требуется копировать весь образ.
    *   **Изоляция изменений**: Запись происходит только в собственный R/W слой контейнера.

```dockerfile
# Dockerfile демонстрирует слоистость
FROM ubuntu:22.04          # Базовый слой (read-only)
RUN apt-get update && apt-get install -y nginx  # Новый слой (read-only)
COPY index.html /var/www/html/ # Ещё один слой (read-only)
CMD ["nginx", "-g", "daemon off;"]
```

4. Дополнительные ключевые технологии

  • Capabilities (Возможности): Позволяют дробить привилегии суперпользователя (root) на отдельные права. Docker по умолчанию удаляет многие capabilities у контейнеров (например, CAP_SYS_ADMIN), следуя принципу наименьших привилегий.

  • Seccomp (Secure Computing Mode): Фильтрует системные вызовы (syscalls), которые может выполнять процесс. Docker использует профиль seccomp по умолчанию, чтобы ограничить набор доступных системных вызовов внутри контейнера, уменьшая поверхность атаки.

  • SELinux/AppArmor: Модули принудительного контроля доступа (MAC), которые обеспечивают дополнительный уровень безопасности, определяя политики доступа для процессов (включая процессы внутри контейнеров) к файлам, портам и другим ресурсам.

Взаимодействие примитивов при запуске контейнера

  1. Инициализация: Демон Docker (dockerd) получает команду на запуск контейнера.
  2. Создание изоляции:
    *   Вызывается системный вызов `clone()` с флагами для создания новых **namespaces** (CLONE_NEWPID, CLONE_NEWNET и т.д.).
    *   Процесс помещается в отдельную **cgroup** для контроля ресурсов.
  1. Подготовка файловой системы: С помощью OverlayFS монтируется корневая файловая система контейнера — объединение слоёв образа и R/W слоя.
  2. Настройка безопасности:
    *   Применяются **capabilities** (удаляются "опасные").
    *   Загружается профиль **seccomp**.
    *   При необходимости применяются политики **SELinux/AppArmor**.
  1. Запуск процесса: В изолированном пространстве запускается процесс, указанный в ENTRYPOINT/CMD (например, /bin/bash).

Это сочетание примитивов позволяет Docker обеспечивать легковесную, быструю и достаточно безопасную изоляцию процессов, которая, однако, отличается от полной виртуализации, так как все контейнеры разделяют ядро хостовой ОС. Именно поэтому контейнеры Linux не могут напрямую запускаться на Windows или macOS без слоя виртуализации (гипервизора).