Что такое Docker и как он устроен
Docker Engine: ядро Docker
Сердцем Docker является Docker Engine — клиент-серверное приложение, состоящее из трёх основных компонентов: Docker Daemon, Docker REST API и Docker CLI.
Docker Daemon
Docker Daemon (dockerd
) — фоновый процесс, отвечающий за управление контейнерами Docker на хосте. Он прослушивает запросы Docker API и обрабатывает создание, выполнение и уничтожение контейнеров. Это мозг Docker, взаимодействующий с операционной системой для изоляции и управления контейнерами, сетями и хранилищами.
- Отвечает за управление жизненным циклом контейнеров (запуск, остановка, перезапуск контейнеров).
- Собирает, извлекает и сохраняет образы Docker из реестров.
- Управляет сетью контейнеров и томами данных.
Docker REST API
Docker REST API позволяет внешним инструментам и приложениям (включая Docker CLI) взаимодействовать с Docker Daemon. Этот API предлагает программный способ управления ресурсами Docker, такими как контейнеры, образы и сети. Docker CLI отправляет демону команды через этот API, например, когда выполняется docker run
или docker build
.
Docker CLI
Docker CLI — инструмент командной строки, с помощью которого разработчики взаимодействуют с Docker. Он предоставляет удобный интерфейс для управления контейнерами, образами, сетями и томами. Каждая команда docker, например docker run
, docker build
или docker ps
, — это команда на стороне клиента, взаимодействующая с Docker Daemon через API.
Образы Docker: Планы контейнеров
Образ Docker — это шаблон, доступный только для чтения, определяющий окружение и зависимости, необходимые для запуска приложения. Он включает в себя всё — от кода приложения до среды выполнения, библиотек и любых настроек конфигурации. Образы Docker создаются послойно.
Слои и UnionFS
Каждый образ Docker состоит из множества слоёв. Эти слои создаются по мере выполнения инструкций в Dockerfile
. Dockerfile
— это обычный текстовый файл с такими командами, как FROM
, COPY
и RUN
, определяющими, что войдёт в образ.
Docker использует UnionFS, позволяющую компоновать несколько слоёв вместе, представляя их контейнеру как единую файловую систему. Этот механизм наслоения позволяет Docker эффективно использовать общие слои для разных образов. Например, если несколько образов используют один и тот же базовый образ (например, Ubuntu), базовый слой используется совместно, что экономит дисковое пространство и ускоряет запуск контейнера.
copy-on-write
Docker использует механизм copy-on-write для контейнеров. Когда контейнер запускается, он первоначально предоставляет доступ к слоям образа в режиме только для чтения. Однако если контейнеру необходимо изменить файл, Docker копирует его из образа в слой, доступный для записи (уникальный для данного контейнера). Этот механизм делает контейнеры лёгкими и эффективными.
Контейнеры: Лёгкие изолированные среды
Контейнер Docker — это экземпляр образа, но это нечто большее, чем просто образ, запущенный в памяти. Контейнеры — это изолированные процессы, выполняющиеся на одном хосте, но ведущие себя так, будто они работают на отдельных машинах.
Изоляция процессов и ресурсов
Контейнеры Docker обеспечивают изоляцию процессов и контроль ресурсов с помощью возможностей ядра Linux, в частности пространств имён и cgroups:
- Пространства имён: Они изолируют такие аспекты окружения контейнера, как файловые системы, идентификаторы процессов (PID) и сетевые интерфейсы. Контейнеры думают, что у них есть свой собственный сетевой стек, дерево процессов и даже привилегии root, но на самом деле всё это относится только к контейнеру.
- PID пространства имён обеспечивают отдельное дерево процессов.
- Сетевые пространства имён предоставляют каждому контейнеру собственный сетевой стек.
- Монтируемые пространства имён создают изолированные файловые системы для контейнеров.
- Cgroups: Группы управления ограничивают, определяют приоритеты и учитывают использование контейнером процессора, памяти и ввода-вывода. Это позволяет одному контейнеру не перегружать систему, отнимая все ресурсы. Использование ресурсов каждым контейнером может быть ограничено с помощью cgroups, что обеспечивает тонкий контроль над распределением ресурсов.
Контейнеры vs. виртуальные машины
В отличие от виртуальных машин (VM), контейнерам не нужна полноценная операционная система для каждого экземпляра. Контейнеры совместно используют ядро ОС хоста, что приводит к меньшим накладным расходам. Благодаря этому контейнеры быстрее запускаются, используют меньше ресурсов и требуют меньше места для хранения, чем VM.
- Контейнеры: Лёгкие, совместно используют ядро ОС хоста, изолируют процессы и ресурсы на уровне пользовательского пространства.
- VM: Тяжёлые, каждая VM имеет собственное ядро ОС, использует технологию гипервизора для изоляции.
UnionFS: Эффективное многоуровневое хранение данных
UnionFS — служба файловых систем, используемая Docker для управления слоями образов и контейнеров. Она позволяет накладывать несколько файловых систем друг на друга, представляя единую целостную файловую систему.
Многослойная архитектура
Каждый слой образа — это, по сути, снапшот файловой системы в определённый момент. Базовым слоем может быть операционная система, например Ubuntu, а каждый последующий слой добавляет что-то (например, установку пакетов, копирование кода). Каждый слой доступен только для чтения. Когда создаётся контейнер, поверх него добавляется новый слой, доступный для записи.
UnionFS гарантирует:
- Многократное использование слоёв: Несколько образов могут совместно использовать слои. Если два образа построены на основе одного базового образа, базовый слой сохраняется на диске только один раз.
- copy-on-write: Когда контейнер изменяет файл, он копирует и изменяет его только в своём слое, доступном для записи, гарантируя, что другие контейнеры и образы, совместно использующие базовые слои, не будут затронуты.
Docker Hub: Маркетплейс образов
Docker Hub — это центральный реестр, в котором пользователи Docker могут находить образы контейнеров и обмениваться ими. Это публичный репозиторий, где разработчики могут загружать, скачивать и делиться предварительно созданными образами Docker.
Публичные и приватные репозитории
Docker Hub предлагает как публичные, так и приватные репозитории. Публичные репозитории доступны всем желающим, и многие популярные приложения (например, Node.js, MySQL и Redis) имеют официальные образы на Docker Hub, что облегчает начало работы. Разработчики также могут хранить приватные образы для более контролируемого доступа.
- Официальные образы: Поддерживаются Docker или поставщиками программного обеспечения.
- Пользовательские образы: Размещаются сообществом или разработчиками для конкретных проектов.
Работа с сетью в Docker
Сеть Docker позволяет контейнерам взаимодействовать друг с другом или с внешним миром. Docker предоставляет несколько сетевых драйверов:
Сетевой Мост/Bridge Network (по умолчанию)
Когда вы запускаете контейнер Docker, по умолчанию он подключается к сетевому мосту, являющейся приватной для хоста. Контейнеры в одном сетевом мосту могут взаимодействовать друг с другом, а внешний мир может получить доступ к контейнеру через маппинг портов.
- Маппинг портов: Это позволяет перенаправлять трафик с порта на хост-машине на контейнер. Например, вы можете назначить порт
80
на хосте на порт80
в контейнере, чтобы открыть веб-сервер.
Сеть Хоста/Host Network
В режиме сети хоста/host network контейнер совместно использует сетевой стек хоста. Это обеспечивает более высокую производительность сети, поскольку отсутствует виртуальный сетевой мост, но также снижает изоляцию, что может представлять угрозу безопасности.
Оверлейная сеть/Overlay Network
Оверлейные сети используются для соединения контейнеров на нескольких хостах Docker, обычно в таких системах оркестровки, как Docker Swarm или Kubernetes. Это позволяет контейнерам, запущенным на разных хостах, взаимодействовать так, как будто они находятся в одной сети.
Тома: Постоянное хранилище
Контейнеры являются эфемерными, то есть их файловая система временная. Любые изменения, сделанные внутри контейнера (например, сохранение данных в базе данных), будут потеряны при его уничтожении. Docker решает эту проблему с помощью томов.
Типы хранилищ
- Volume: Управляемые Docker, тома хранятся на хост-машине и могут совместно использоваться контейнерами. Они являются рекомендуемым способом сохранения данных, поскольку не зависят от жизненного цикла контейнера.
- Bind mount: Позволяет подключить к контейнеру определённый каталог на хост-машине. Это полезно, когда нужно, чтобы контейнер напрямую взаимодействовал с файловой системой хоста (например, в средах разработки).
- tmpfs: Временное хранилище на основе памяти, используемое для хранения эфемерных данных, которые не должны сохраняться за пределами времени работы контейнера.
Тома гарантируют, что даже если контейнеры будут удалены или пересозданы, важные данные останутся в безопасности и могут быть переданы между контейнерами.
Заключение: Эффективная и гибкая архитектура Docker
Архитектура Docker разработана для обеспечения эффективности, переносимости и масштабируемости. Сочетая контейнеры, легковесные процессы и общую архитектуру ядра с такими мощными инструментами, как UnionFS, сети и тома, Docker позволяет разработчикам упаковывать приложения и запускать их в различных средах.
Кроме того, Docker обладает высокой степенью модульности и интегрируется с современными облачными экосистемами, позволяя осуществлять оркестровку в масштабе (с помощью таких инструментов, как Docker Swarm или Kubernetes). Именно благодаря этой гибкой и эффективной архитектуре Docker стал фундаментальным инструментом в современной разработке программного обеспечения.