Модель композиции (Docker Compose)
TL;DR: Docker Compose — декларативное описание многоконтейнерного приложения. Один YAML-файл заменяет десятки
docker runкоманд. Service ≠ Container.
Docker Compose — это инструмент для определения и запуска многоконтейнерных приложений. Он совершает парадигмальный сдвиг в работе с Docker: переход от императивного управления отдельными контейнерами к декларативному описанию всей системы.
Compose реализует подход Infrastructure as Code (IaC) для локальной среды разработки.
Декларативный vs Императивный подход
- Императивный (Docker CLI): Вы говорите системе что сделать.
docker run -d --network app-net --name db postgresЕсли вы выполните эту команду дважды, вы получите ошибку (конфликт имен). Вам нужно писать скрипты для проверки состояния, создания сетей и т.д. - Декларативный (Compose): Вы описываете желаемое состояние системы в YAML-файле.
docker compose upCompose смотрит на текущее состояние, сравнивает его с желаемым и выполняет только необходимые действия (конвергенция). Если контейнер уже запущен и его конфигурация не изменилась, Compose его не тронет. Если изменилась — пересоздаст.
Структура проекта
Compose вводит понятие Проекта — логической группы ресурсов, изолированных от других проектов.
1. Service (Сервис) vs Container (Контейнер)
Важно различать эти понятия:
- Service: Это абстрактное определение, конфигурация (шаблон). “Мне нужен веб-сервер на базе Nginx с такими-то портами”.
- Container: Это конкретный запущенный экземпляр сервиса.
В большинстве случаев у сервиса один контейнер (1:1), но Compose позволяет масштабировать сервисы (scale: 3), создавая несколько реплик (контейнеров) из одного определения сервиса (1:N).
2. Изоляция проектов
Имя проекта (по умолчанию — имя папки) используется как префикс для всех создаваемых ресурсов (сетей, томов, контейнеров).
- Папка
my-shop→ контейнерmy-shop-db-1, сетьmy-shop_default. - Это позволяет запускать несколько копий одного и того же окружения на одной машине (например, в CI/CD агентах), просто меняя имя проекта (
-p project_name).
Управление зависимостями
В микросервисной архитектуре порядок запуска критичен. Backend не должен падать, если Database еще не готова принимать соединения.
depends_on
Определяет порядок запуска и остановки.
depends_on: [db]: Гарантирует, что Docker отправит команду старта контейнеруdbраньше, чемbackend.- Проблема: Docker считает контейнер запущенным, как только процесс стартовал (PID появился). Но базе данных может потребоваться 10-30 секунд на инициализацию (создание файлов, восстановление журнала). Приложение попытается подключиться сразу и упадет.
Healthchecks (Проверки здоровья)
Для решения проблемы “RACE Condition” (гонки) Compose использует Healthchecks.
- В сервисе БД описывается, как проверить ее готовность (например, команда
pg_isready). - В зависимом сервисе используется расширенный синтаксис:
depends_on: db: condition: service_healthy
Теперь Compose не просто запустит базу, но будет ждать, пока она не ответит “OK”, и только потом запустит Backend.
Сетевое взаимодействие
Compose автоматически создает единую сеть для проекта (обычно типа bridge).
- Service Discovery: Имя сервиса в YAML становится DNS-именем. Сервис
webможет обратиться к базе по адресуpostgres://db:5432(гдеdb— имя сервиса). - Внутренние порты открыты для всех участников сети проекта, даже если они не опубликованы (
ports) на хост-машину.
Профили и Переопределения (Overrides)
Docker Compose позволяет управлять сложностью конфигурации через наслоение (Layering).
- Profiles: Позволяют включать/выключать группы сервисов.
- Пример:
profiles: ["debug"]для phpMyAdmin или визуализаторов логов. Они не запустятся поdocker compose up, пока вы явно не укажете--profile debug.
- Пример:
- Overrides: Compose по умолчанию читает
compose.yamlиcompose.override.yaml, объединяя их.compose.yaml: Базовая структура (образы, связи).compose.override.yaml: Локальные настройки (порты, bind mounts для кода), которые не коммитятся в git.compose.prod.yaml: Настройки для продакшена (политика рестарта, production-ready конфиги), применяемые поверх базы.
Подводные камни
| Заблуждение | Реальность |
|---|---|
| «depends_on гарантирует готовность БД» | depends_on ждёт только запуск процесса, не готовность. Используй condition: service_healthy |
| «docker compose down удалит данные» | По умолчанию volumes сохраняются. Для удаления: docker compose down -v |
| «Compose — это для production» | Compose подходит для dev и простого prod. Для серьёзного production — Swarm/K8s |
| «Имя сервиса = имя контейнера» | Имя контейнера = <project>_<service>_<replica>. Сервис — DNS-имя внутри сети |