Ответ
Docker (контейнеризация в целом) — это не виртуализация, а изоляция процессов с помощью встроенных механизмов ядра Linux. Я как DevOps-инженер должен понимать их для глубокой отладки и настройки.
1. Пространства имен (Namespaces): Обеспечивают изоляцию, давая контейнеру его собственное "представление" о системе.
- PID namespace: Изолирует дерево процессов. Процессы в контейнере видят только свои PID'ы, начиная с 1.
- Network namespace: У контейнера свой сетевой стек (интерфейсы, таблицы маршрутизации, iptables правила). Docker создает виртуальные интерфейсы (veth pairs) для связи с хостом.
- Mount namespace: Изолированное дерево файловых систем. Это основа для файловой системы контейнера.
- UTS namespace: Позволяет контейнеру иметь свое собственное имя хоста (
hostname). - IPC namespace: Изолирует механизмы межпроцессного взаимодействия (очереди сообщений, сегменты разделяемой памяти).
- User namespace: Маппинг UID/GID внутри контейнера на непривилегированные UID/GID на хосте для повышения безопасности.
2. Группы управления (Control Groups - cgroups): Ограничивают и учитывают использование ресурсов.
- cpu, cpuacct: Ограничивают долю CPU и ведут его учет.
- memory: Устанавливают лимиты на использование RAM и подкачки (swap), следят за потреблением.
- blkio: Контролируют операции ввода-вывода на блочных устройствах (дисках).
- pids: Ограничивают количество процессов.
3. Файловые системы (Union File Systems): OverlayFS (стандарт для современных ядер) позволяет объединять несколько слоев (read-only образ + read-write слой контейнера) в единое представление. Это делает образы легковесными и многоразовыми.
4. Механизмы безопасности:
- Capabilities: Разделяет привилегии суперпользователя. Контейнеру по умолчанию дается только ограниченный набор capabilities (например, нет
CAP_SYS_ADMIN). - Seccomp: Фильтрует системные вызовы, которые может выполнять процесс в контейнере, блокируя опасные.
- AppArmor/SELinux: Применяют Mandatory Access Control (MAC) политики к процессам контейнера.
Практическая проверка:
# Посмотреть PID контейнера и его namespaces
CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' my_container)
ls -la /proc/$CONTAINER_PID/ns/
# Посмотреть cgroup контейнера
cat /proc/$CONTAINER_PID/cgroup