Внутреннее устройство контейнеров: изоляция через namespac... | Вопросы для собеседования | Skilio
Внутреннее устройство контейнеров: изоляция через namespaces, cgroups и многослойную файловую систему
Вопрос:

Можете ли вы объяснить основную идею контейнеров в Docker?

Подсказки:

  • Подумайте о том, как Docker разделяет процессы на одном хосте
  • Основные команды docker и docker-compose
  • Учтите, какие функции Linux использует Docker для достижения изоляции
  • Объясните что такое Docker-слои в контексте файловых систем

Выше ожиданий:

  • Понимание cgroups и namespaces в Linux
  • Внутреннее устройство файловой системы UnionFS/overlay
  • Границы безопасности контейнеров
  • Rootles контейнеры
  • Многоэтапные сборки
Ответ:

Основная идея изоляции контейнеров в Docker

Основы изоляции контейнеров

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

Изоляция контейнеров гарантирует:

  • Приложения и их зависимости запускаются в одной среде
  • Процессы внутри одного контейнера не могут напрямую получить доступ к ресурсам другого контейнера
  • Ресурсы могут быть распределены и ограничены для каждого контейнера
  • Контейнеры могут легко перемещаться между средами

Технологии Linux, обеспечивающие изоляцию

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

Namespaces обеспечивают изоляцию, создавая отдельные экземпляры глобальных системных ресурсов, которые может видеть процесс. Каждый контейнер получает собственный набор пространств имён, создавая иллюзию наличия собственного изолированного экземпляра операционной системы.

Docker использует несколько типов пространств имён:

  • PID namespace: Изолирует идентификаторы процессов. Процессы в одном контейнере не могут видеть или влиять на процессы в другом контейнере или на хост-системе.
  • NET namespace: Обеспечивает изоляцию сети. Каждый контейнер имеет собственный сетевой стек, включая сетевые интерфейсы, IP-адреса и таблицы маршрутизации.
  • MNT namespace: Изолирует точки монтирования файловой системы. Контейнеры имеют свою собственную ФС.
  • UTS namespace: Позволяет каждому контейнеру иметь собственное имя хоста и доменное имя.
  • IPC namespace: Изолирует ресурсы межпроцессного взаимодействия.
  • USER namespace: Маппит (отображает) идентификаторы пользователей между контейнером и хостом, что позволяет использовать не-root пользователей внутри контейнеров.

Группы управления ресурсами (cgroups)

Группы управления ресурсами (cgroups) позволяют Docker ограничивать и распределять ресурсы для контейнеров, включая:

  • Использование процессора: Ограничивать, сколько времени процессора может использовать контейнер
  • Память: Ограничивать доступную память для контейнера
  • Ввод/вывод на блочных устройствах: Управлять доступом контейнера к вводу/выводу на дисках
  • Пропускная способность сети

Пример ограничения ресурсов контейнера:

docker run --memory="512m" --cpus="1.5" nginx

Это ограничивает контейнер nginx до 512 МБ памяти и 1,5 процессорных ядер.

Layered Filesystem Architecture

Docker использует подход слоев файловой системы, который способствует изоляции:

Union File System (UnionFS)

Docker реализует Union File System стратегию, как правило, используя OverlayFS. Которая позволяет файлам добавлять, редактировать, удалять файлы через вышележащие слои. Получая конечную файловую систему.

Преимущества:

  • Эффективность: Слои могут быть совместно использованы между контейнерами
  • Скорость: Быстрый старт новых контейнеров, так как они используют существующие слои
  • Экономия места: Только различия между контейнерами занимают дополнительное место

Слои образов и контейнеров

  • Базовый образ: Основополагающий слой, содержащий файлы ОС
  • Слои приложений: Добавляются поверх базового слоя, содержащие код приложения и зависимости
  • Слой контейнера: Записываемый слой, добавляемый при запуске контейнера

При модификации файла в контейнере используется стратегия copy-on-write:

  1. Файл копируется из только-для-чтения слоя в записываемый слой контейнера
  2. Копия изменяется, а оригинал остаётся неизменным
  3. Другие контейнеры, использующие тот же образ, продолжают видеть неизменённый файл

Многоэтапные сборки (multi-stage build)

Многоэтапные сборки позволяют использовать несколько инструкций FROM в Dockerfile. Это помогает:

  • Создавать более компактные конечные образы, включая только необходимые артефакты
  • Разделять средства сборки от среды выполнения
  • Снизить поверхность атаки, устраняя ненужные компоненты

Пример многоэтапной сборки Dockerfile:

# Этап сборки
FROM node:14 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Этап production образа
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Команды Docker для управления контейнерами

Основные команды Docker

# Сборка изображения из Dockerfile
docker build -t my-app:1.0 .

# Запуск контейнера
docker run -d -p 8080:80 --name web-app my-app:1.0

# Список запущенных контейнеров
docker ps

# Просмотр логов контейнера
docker logs web-app

# Выполнение команды внутри запущенного контейнера
docker exec -it web-app bash

# Остановка и удаление контейнера
docker stop web-app
docker rm web-app

# Список изображений
docker images

# Удаление изображения
docker rmi my-app:1.0

Docker Compose

Docker Compose позволяет определять многоконтейнерные приложения в файле YAML:

# Запуск сервисов, определённых в docker-compose.yml
docker-compose up -d

# Просмотр запущенных сервисов
docker-compose ps

# Остановка сервисов
docker-compose down

Границы безопасности контейнеров

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

  • Эксплойты ядра могут повлиять на все контейнеры и хост
  • Привилегированные контейнеры могут получить доступ к ресурсам хоста
  • Конкуренция за ресурсы может возникнуть, несмотря на ограничения cgroup

Рекомендации по лучшим практикам включают:

  • Запуск контейнеров от имени не root пользователя
  • Использование принципа наименьших привилегий
  • Регулярное обновление базовых образов и сканирование на предмет уязвимостей
  • Использование только-для-чтения файловых систем по возможности

Безопасные контейнеры (rootless containers) работают без необходимости root-привилегий на хосте, что повышает безопасность:

  • Процессы контейнеров отображаются как непривилегированные пользователи на хосте
  • Снижает риск атак на выход из контейнера
  • Ограничивает потенциальный ущерб, если контейнер скомпрометирован

Включение rootless режима требует специфической настройки демона Docker.

0
DevOps Новичок Опубликовано
© Skilio, 2025
Условия использования
Политика конфиденциальности
Мы используем файлы cookie, для персонализации сервисов и повышения удобства пользования сайтом. Если вы не согласны на их использование, поменяйте настройки браузера.