Что такое Docker Compose
В реальном мире приложение редко состоит из одного контейнера: бэкенду на Java нужны база данных PostgreSQL, кэш Redis, брокер сообщений Kafka и панель мониторинга.
🟢 Junior Level
30-секундный ответ
Docker Compose — это декларативный инструмент для оркестрации и одновременного запуска многоконтейнерных приложений (Multi-Container Applications) на одном сервере с помощью одного файла конфигурации compose.yaml (или docker-compose.yml).
В реальном мире приложение редко состоит из одного контейнера: бэкенду на Java нужны база данных PostgreSQL, кэш Redis, брокер сообщений Kafka и панель мониторинга.
- Вместо того чтобы вручную выполнять десятки длинных команд
docker runс настройкой портов, томов и сетей, вы описываете всю систему в YAML-файле. - Команда
docker compose up -dодной операцией создаёт виртуальную сеть, выделяет тома и поднимает все взаимосвязанные сервисы в правильном порядке.
Наглядная аналогия из жизни
- Docker CLI (
docker run) — это управление отдельными музыкантами: вы подходите к барабанщику, гитаристу и пианисту и каждому отдельно говорите, когда начинать играть. - Docker Compose — это дирижёр оркестра: по единой партитуре (
compose.yaml) он взмахом палочки запускает весь оркестр синхронно, следит за тем, чтобы музыканты слышали друг друга (сеть) и чтобы пианино было настроено до начала симфонии (depends_on).
Наглядный пример для Spring Boot 3 и PostgreSQL
# compose.yaml (в современных версиях поле 'version' устарело и не требуется)
services:
app:
build: .
ports:
- "8080:8080"
environment:
# Сервисы обращаются друг к другу по имени сервиса 'postgres-db':
- SPRING_DATASOURCE_URL=jdbc:postgresql://postgres-db:5432/orders_db
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=secret
depends_on:
postgres-db:
condition: service_healthy # Ждём реальной готовности БД!
postgres-db:
image: postgres:16-alpine
environment:
- POSTGRES_DB=orders_db
- POSTGRES_PASSWORD=secret
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
pgdata: # Именованный том для сохранения данных БД
# Запуск всей инфраструктуры в фоновом режиме:
docker compose up -d
# Просмотр логов бэкенда в реальном времени:
docker compose logs -f app
# Полная остановка всех сервисов и удаление сетей:
docker compose down
🟡 Middle Level
Внутренняя сеть и встроенный DNS (Embedded DNS)
Когда Docker Compose поднимает сервисы:
- Он автоматически создаёт изолированную виртуальную сеть типа bridge (по умолчанию
project_default). - Внутри этой сети активируется встроенный DNS-сервер Docker (доступный по служебному адресу
127.0.0.11). - Имена сервисов в YAML становятся доменными именами: Java-приложению не нужно знать IP-адрес базы данных; вызов
postgres-db:5432автоматически резолвится в текущий внутренний IP-адрес контейнера базы данных.
ports vs expose
ports: ["8080:8080"]: пробрасывает порт контейнера на физический сетевой интерфейс хост-машины (Host Port Binding). Сервис становится доступен извне контейнерной сети (например, в браузере разработчика по адресуhttp://localhost:8080).expose: ["5432"]: открывает порт только для других контейнеров внутри общей Docker-сети, не публикуя его на хосте. Это безопасный выбор для баз данных и внутренних брокеров, защищающий их от внешних атак.
Ловушка depends_on и правильный Healthcheck
Начинающие разработчики часто сталкиваются с ошибкой:
# ❌ НЕПРАВИЛЬНО: Приложение упадёт при старте!
services:
app:
depends_on:
- postgres-db
- Почему это ломается: по умолчанию
depends_onгарантирует только факт запуска процесса контейнера БД. - Но СУБД PostgreSQL после старта выполняет инициализацию файлов и создание баз данных, что занимает 3–10 секунд.
- Приложение Spring Boot стартует быстрее, пытается установить соединение с базой, получает
Connection refusedи падает сApplication failed to start. - Решение: использовать
condition: service_healthyв сочетании с директивойhealthcheck: test: ["CMD-SHELL", "pg_isready"].
🔴 Senior Level
Интеграция Spring Boot 3.1+ с Docker Compose (Auto-Configuration)
В Spring Boot 3.1 появилась революционная нативная интеграция с Docker Compose (spring-boot-docker-compose):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
- Автоматический запуск: при выполнении команды
mvn spring-boot:runв IDE Spring Boot сам находит файлcompose.yamlв корне проекта и выполняетdocker compose up. - Динамическая инъекция Connection Details: Spring Boot самостоятельно парсит открытые порты Postgres, Redis или Kafka и динамически инжектирует JDBC URL, username и password в
ApplicationContextбез необходимости ручной настройкиapplication.yml! - Автоматическая остановка: при остановке приложения в IDE Spring Boot автоматически гасит контейнеры.
Сетевая сегментация безопасности (Zero Trust Networks)
В Production-окружении монолитная общая сеть является риском безопасности. Compose позволяет разделить топологию:
services:
api-gateway:
image: nginx:alpine
ports: ["80:80"]
networks: [frontend-net]
order-service:
image: order-service:1.0
networks: [frontend-net, backend-net]
postgres-db:
image: postgres:16-alpine
networks: [backend-net] # БД физически изолирована от Nginx!
networks:
frontend-net:
backend-net:
Злоумышленник, скомпрометировавший веб-сервер Nginx, физически не сможет отправить пакеты в порт 5432 базы данных PostgreSQL.
Горизонтальное масштабирование (--scale) и коллизия портов
Команда docker compose up --scale order-service=3 позволяет запустить 3 реплики сервиса.
- Ловушка: если в
compose.yamlобъявлен статический маппингports: ["8080:8080"], запуск масштабирования упадёт с ошибкойBind for 0.0.0.0:8080 failed: port is already allocated. - Решение для масштабирования: указывать только порт контейнера без привязки к порту хоста (
ports: ["8080"]) для случайного выделения порта, либо использовать только внутреннюю сеть с балансировщиком нагрузки (Nginx/Traefik).
4 Tricky Questions
1. Почему команда docker compose up --scale service=3 падает с ошибкой, если у сервиса указан маппинг ports: ["8080:8080"], и как настроить балансировку?
Ответ:
Сетевой стек операционной системы хоста не позволяет двум разным процессам занять один и тот же TCP-порт (8080) на одном сетевом интерфейсе (ошибка Address already in use).
Чтобы масштабировать сервис:
- Убрать маппинг портов на хост или указать диапазон:
ports: ["8080-8082:8080"](или динамический порт"8080"). - Запустить перед масштабируемыми сервисами легковесный обратный прокси (Nginx или Traefik), подключённый к той же сети. Прокси принимает трафик на внешний порт
80и балансирует входящие запросы между тремя контейнерами по их внутреннему DNS-имени сервиса (Docker DNS автоматически распределяет запросы методом Round-Robin).
2. В чём фундаментальная разница между командами docker compose down и docker compose down -v? К какой катастрофе может привести случайное добавление флага -v?
Ответ:
docker compose down: останавливает и удаляет запущенные контейнеры и созданные виртуальные сети, но оставляет нетронутыми именованные тома (Volumes). Данные базы данных на диске сохраняются в полной безопасности.docker compose down -v(или--volumes): вместе с контейнерами безвозвратно удаляет все именованные тома, объявленные в секцииvolumes:! Если выполнить эту команду на сервере с рабочей базой данных, весь каталог/var/lib/postgresql/dataбудет мгновенно стёрт с диска без возможности восстановления.
3. Почему Java-приложение, запущенное локально в IDE на хост-машине (не в Docker), не может подключиться к БД по адресу jdbc:postgresql://postgres-db:5432/mydb, объявленному в compose.yaml?
Ответ:
Доменное имя сервиса postgres-db регистрируется только во внутреннем DNS-сервере Docker (127.0.0.11), работающем исключительно внутри созданной виртуальной сети bridge.
Операционная система хоста использует свой собственный системный DNS (роутер или провайдер) и не имеет доступа к DNS-таблицам Docker.
Чтобы локальное приложение из IDE подключилось к БД:
- В секции
postgres-dbдолжен быть проброшен порт на хост:ports: ["5432:5432"]. - В локальном
application.ymlадрес должен указывать на хост:jdbc:postgresql://localhost:5432/mydb.
4. Что такое файлы оверрайдов (docker-compose.override.yml), и как они объединяются с основным файлом конфигурации?
Ответ:
По умолчанию при запуске docker compose up движок автоматически ищет два файла: основной compose.yaml и файл переопределений docker-compose.override.yml, выполняя их глубокое слияние (Deep Merge):
- Конфигурации объединяются: если в основном файле указан
image, а в override указанports: ["5432:5432"]и локальныйbuild: ., то итоговый сервис объединит обе директивы. - Списки (например,
ports,environment) конкатенируются. - Это позволяет держать в репозитории чистый базовый
compose.yamlдля тестовых стендов, а разработчикам локально создавать.override.yml(добавленный в.gitignore) для проброса локальных портов отладки и подключения исходников через volume.
🎯 Шпаргалка для интервью
Главное о Docker Compose
- Что это: инструмент оркестрации многоконтейнерных систем на одном хосте.
- Конфигурация: файл
compose.yaml(секции:services,networks,volumes). - Сетевое взаимодействие: встроенный DNS (
127.0.0.11); контейнеры общаются по имени сервиса. - Синхронизация старта: использовать
depends_onв связке сcondition: service_healthy. - Spring Boot 3.1+: библиотека
spring-boot-docker-composeавтоматически поднимает инфраструктуру при старте приложения. - Хранение данных: данные БД сохранять строго в именованных
volumes:. - Ограничения: предназначен для одного хоста; не заменяет Kubernetes в production (нет multi-node, нет HPA, нет rolling update).
Docker Compose vs Kubernetes
| Критерий | Docker Compose | Kubernetes |
| :— | :— | :— |
| Среда применения | Локальная разработка, простые VPS | Крупный продакшен, облака |
| Количество узлов | Строго 1 хост-сервер | Кластер из сотен серверов |
| Автомасштабирование| ❌ Нет | 🟢 Есть (Horizontal Pod Autoscaler) |
| Self-Healing | ❌ Ограничен (restart: always) | 🟢 Автоперезапуск и миграция подов |
| Сложность порога входа | 🟢 Низкая (несколько часов) | 🔴 Высокая (недели обучения) |
Красные флаги на собеседовании (Чего говорить нельзя)
- ❌ «depends_on гарантирует, что БД полностью готова к приёму запросов» — он ждёт только старта контейнера; нужен
service_healthy. - ❌ «Docker Compose используется для управления кластером из 10 серверов в продакшене» — Compose работает только на одной машине.
- ❌ «Чтобы удалить контейнеры, я всегда пишу docker compose down -v» — флаг
-vуничтожает все данные баз данных в volumes!