Ответ
Docker-контейнер — это не виртуальная машина, а изолированный процесс в Linux, который создаётся и ограничивается с помощью комбинации функций ядра. Основные компоненты:
1. Linux Namespaces (пространства имён) — обеспечивают изоляцию.
- PID namespace: Контейнер видит только свои собственные процессы, его PID 1 — это процесс entrypoint.
- Network namespace: У контейнера свой собственный сетевой стек: интерфейсы, IP-адрес, таблицы маршрутизации и iptables правила.
- Mount namespace: Изолированное дерево файловой системы. Контейнер не видит хостовые каталоги, если они не смонтированы явно.
- UTS namespace: Позволяет контейнеру иметь своё собственное имя хоста (hostname).
- IPC namespace: Изолирует межпроцессное взаимодействие (очереди сообщений, сегменты разделяемой памяти).
- User namespace: (опционально) Позволяет мапить UID/GID внутри контейнера на другие UID/GID на хосте, повышая безопасность.
2. Control Groups (cgroups) — обеспечивают ограничение ресурсов и учёт.
- Ограничивают и отслеживают использование ресурсов процессом (и его потомками).
# Пример: Docker создаёт cgroup для контейнера с лимитами docker run -it --cpus="1.5" --memory="512m" alpine:latest - Управляют CPU, памятью, дисковым I/O, сетью.
3. Union File System (UnionFS) — обеспечивает слои образов.
- Образ контейнера состоит из неизменяемых слоёв (read-only). При запуске контейнера поверх них добавляется тонкий слой для записи (copy-on-write).
- Драйверы:
overlay2(рекомендуемый),aufs,devicemapper.
4. Демон Docker и инструментарий.
- dockerd: Демон, управляющий контейнерами, образами, сетями.
- containerd: Низкоуровневый рантайм, который фактически запускает контейнеры.
- runc: Инструмент CLI для создания и запуска контейнеров согласно спецификации OCI.
Проверка изоляции:
# Посмотреть процессы внутри контейнера с его точки зрения (PID namespace)
docker exec my_container ps aux
# Посмотреть, как эти процессы выглядят с хоста (они обычные процессы)
ps aux | grep <process_from_container>
# Увидеть cgroup контейнера
cat /sys/fs/cgroup/memory/docker/<container_id>/memory.limit_in_bytes
Контейнеры разделяют ядро хоста, поэтому нельзя запустить контейнер с Linux внутри Windows-хоста без виртуализации (используются Windows Containers с другим механизмом).