Как устроен Docker: что происходит «под капотом»


Поговорим немного про базу.

Docker — одно из самых популярных и любимых разработчиками средств контейнеризации. Его простота снаружи скрывает сложную, продуманную архитектуру внутри. Разберёмся, что делает Docker, как он работает, и что скрывается под его интерфейсом.

Наш телеграм канал про Docker и Devops, мы разбираем всю базу в нагляхных картниках и шорстах.

1) Что такое Docker контейнер?

Контейнер — это изолированная среда, в которой выполняется приложение со всеми его зависимостями, библиотеками и настройками.
⚠️ Важно: контейнер не виртуальная машина. Он делит ядро ОС с хостом, но видит только ограниченную часть системы через механизмы изоляции.

2) Основные компоненты Docker

Давайте посмотрим, из чего состоит Docker.

  • Docker Engine
    – Docker Daemon (dockerd) — серверный процесс, который управляет контейнерами, образами, сетями и т.д.
    – Docker CLI (docker) — командная строка, через которую мы общаемся с dockerd.
    – REST API — интерфейс взаимодействия (CLI, SDK и другие клиенты общаются с Daemon через API).

👉 Пример: когда вы пишете docker run nginx, CLI отправляет запрос в Daemon, который ищет образ, создает контейнер и запускает его.

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

Это ключевой механизм изоляции в Linux, который даёт контейнеру собственный:

  • процессный ID (pid namespace)
  • файловую систему (mnt namespace)
  • сеть (net namespace)
  • hostname (uts namespace)
  • IPC (ipc namespace)

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

👉 Благодаря namespace контейнер видит «свою» мини-ОС, хотя на самом деле он просто ограничен виртуальными «шторами» внутри Linux.

4) Cgroups (Control Groups)

Отвечают за ограничение и учёт ресурсов: CPU, RAM, I/O, network.

  • Например, можно задать контейнеру лимит использования 512 МБ памяти и 0.5 CPU.
  • Если приложение выйдет за лимит — контейнер будет остановлен или ограничен.

Без cgroups контейнеры могли бы потреблять неограниченные ресурсы и влиять на другие процессы хоста.

5) Union File Systems (OverlayFS)

Docker использует многослойную файловую систему, где образы состоят из слоёв.

Каждый Dockerfile шаг создаёт новый слой. При запуске контейнера создаётся новый верхний «writable» слой, все остальные — read-only.

Пример: если у вас 10 контейнеров из одного образа, они разделяют слои, экономя место.

6) Container Runtime

Под капотом Docker использует runtime, чтобы запустить контейнер. По умолчанию это runc, соответствующий стандарту OCI Runtime Specification.

👉 Когда Daemon создает контейнер, он вызывает runc, который через системные вызовы clone(), setns() и chroot() изолирует процесс.

(Раньше Docker использовал libcontainer, потом переключился на runc — open-source runtime от Docker)

7) Docker Images

Образы Docker — это read-only слои, собранные в Union FS.
Каждый слой содержит изменения относительно предыдущего (например, установка пакета → новый слой).

Сборка образа: происходит пошагово, на каждом шаге Dockerfile создаётся новый слой.

Хранение образов: локально (в /var/lib/docker) или в реестре (Docker Hub, GitLab Container Registry, AWS ECR).

8) Docker Networking

Docker создает виртуальные сети (bridge, overlay, host), которые соединяют контейнеры друг с другом и с внешним миром.

👉 По умолчанию контейнеры подключаются к bridge-сети и получают IP-адреса из внутреннего пула.

Можно пробросить порты через -p, создать собственные сети, подключить контейнеры через docker network connect.

В Swarm-режиме используется Overlay network, которая соединяет контейнеры через разные хосты.

9) Безопасность Docker

Docker использует:

  • seccomp (ограничение системных вызовов)
  • AppArmor / SELinux (ограничение привилегий)
  • user namespaces (отображение UID контейнера в другой UID на хосте)

⚠️ По умолчанию контейнеры достаточно «мощные» (например, могут видеть ядро через /proc), поэтому для production нужно дополнительно ужесточать настройки (например, --cap-drop).

10) Что происходит, когда вы пишете docker run nginx?

Пошагово:

  1. CLI отправляет запрос Daemon’у через API
  2. Daemon ищет образ (локально или в registry)
  3. Создаётся read-write слой контейнера
  4. Создаётся namespace (pid, net, mnt…)
  5. Применяются cgroups для лимитов
  6. Вызывается runc → процесс изолируется
  7. Контейнер подключается к сети
  8. Запускается ENTRYPOINT/command

Контейнер работает, пока процесс внутри жив.

11) Почему Docker — это не магия?

Docker использует стандартные возможности ядра Linux (namespaces, cgroups, chroot, seccomp, overlayfs), оборачивая их в удобный API и CLI.

Контейнер — просто изолированный процесс, а не полноценная VM.
Поэтому Docker такой быстрый, лёгкий и удобный.

12) Заключение

Под капотом Docker — сложная экосистема на базе Linux:

  • namespaces — изоляция
  • cgroups — контроль ресурсов
  • runc — запуск контейнеров
  • overlayfs — многослойная файловая система
  • REST API + Daemon + CLI — взаимодействие

Docker скрывает технические детали, позволяя сосредоточиться на простом запуске, сборке и развертывании приложений.

Теперь, зная, что происходит внутри, вы сможете глубже понять работу контейнеров, лучше их настраивать, дебажить и оптимизировать.

🔥 Если интересно, могу отдельно рассказать про Docker vs Kubernetes, Docker security или строительство минимальных образов — пиши!

+1
1
+1
1
+1
0
+1
0
+1
0

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *