В чем разница между ресурсами хостовой машины и ресурсами Docker-контейнера?

«В чем разница между ресурсами хостовой машины и ресурсами Docker-контейнера?» — вопрос из категории Docker, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Docker-контейнеры не виртуализируют железо, а используют механизмы изоляции ядра Linux (namespaces, cgroups) для создания изолированных окружений. Поэтому их ресурсы — это часть ресурсов хоста, но с наложенными ограничениями.

Ключевые различия

Аспект Ресурсы хостовой машины (Host OS) Ресурсы Docker-контейнера
Ядро (Kernel) Собственное ядро ОС. Разделяет ядро хоста. Контейнер не может использовать другую версию ядра или модули, отсутствующие на хосте.
Память (RAM) Вся физическая и виртуальная память системы. Выделяется из памяти хоста. По умолчанию контейнер может использовать всю свободную память хоста, что может привести к OOM Kill. Необходимо явно ограничивать.
ЦПУ (CPU) Все процессорные ядра/потоки. По умолчанию не ограничен и может использовать все доступные циклы CPU. Необходимо явно ограничивать долю или количество ядер.
Файловая система Корневая ФС хоста и подключенные диски. Имеет собственную изолированную корневую ФС (образ контейнера), но по умолчанию может монтировать любые директории хоста (если не ограничено).
Сеть Сетевые интерфейсы хоста, правила iptables. По умолчанию создается виртуальный сетевой интерфейс (veth), подключенный к docker-бриджу (docker0). Контейнер получает свой IP в этой приватной сети.
Процессы Видит все процессы системы (через ps aux). Видит только свои собственные процессы и, возможно, процессы ядра (в зависимости от настроек namespace). Процессы в контейнере — это обычные процессы на хосте, их можно увидеть с ps aux на хосте, если знать PID.

DevOps-практика: Управление ресурсами

Без явных ограничений контейнер может исчерпать ресурсы хоста («шумный сосед»). Ограничения задаются через docker run или в docker-compose.yml.

1. Ограничение памяти и подкачки:

docker run -d --name myapp 
  --memory="512m"           # Максимум 512 МБ RAM
  --memory-swap="1g"        # Максимум 1 ГБ RAM + Swap (swap = 1g - 512m = 512m)
  --memory-reservation="256m"  # Мягкий лимит, который Docker пытается соблюдать
  my-image

2. Ограничение CPU:

docker run -d --name myapp 
  --cpus="1.5"              # Может использовать максимум 1.5 ядра
  --cpuset-cpus="0,3"        # Привязать только к ядрам 0 и 3
  my-image

3. В Docker Compose:

version: '3.8'
services:
  app:
    image: my-image
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

4. Мониторинг: Используйте docker stats или интеграции с Prometheus (cAdvisor) для отслеживания реального потребления ресурсов контейнерами.

docker stats --all --format "table {{.Name}}t{{.CPUPerc}}t{{.MemUsage}}t{{.MemPerc}}"

Важно: Эти ограничения реализуются через механизм control groups (cgroups) в ядре Linux. В Kubernetes аналогичные ограничения задаются через requests и limits в манифестах Pod.