Реальное приложение редко запускается само по себе. Ему нужна база данных, брокер сообщений, кэш. Docker Compose позволяет описать все эти сервисы в одном файле и запустить их вместе — одной командой.
Проблема: запускать всё вручную утомительно
Представьте типичное окружение для разработки: Spring Boot приложение, Postgres, Kafka, Zookeeper. Без Compose каждый участник команды вручную запускает каждый контейнер, передаёт правильные переменные окружения, пробрасывает порты, следит за порядком запуска. При смене машины или переключении между проектами всё повторяется заново.
Классическая жалоба — «на моей машине работает». Чаще всего причина в том, что локальное окружение отличается от коллежского: другая версия Postgres, другой порт, другая переменная окружения. Docker Compose решает именно эту проблему: конфигурация окружения лежит в файле в репозитории и воспроизводима на любой машине.
Короткая формула: один файл docker-compose.yml — одна команда docker compose up — готовое окружение.
Что такое Docker Compose
Docker Compose — инструмент для описания и запуска многоконтейнерных приложений. Вы описываете все нужные сервисы, их настройки, связи между ними и тома в одном YAML-файле. Compose читает этот файл и управляет жизненным циклом всех контейнеров: запуск, остановка, пересборка.
Начиная с Docker Desktop и актуальных версий Docker Engine, Compose встроен в CLI как плагин — команда выглядит как docker compose (без дефиса).
Структура docker-compose.yml
Рассмотрим минимальный пример: Spring Boot приложение + Postgres.
services:
db:
image: postgres:16
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myapp
POSTGRES_PASSWORD: secret
ports:
- "5432:5432" # порт хоста : порт контейнера
volumes:
- postgres_data:/var/lib/postgresql/data # том для хранения данных между перезапусками
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp"]
interval: 5s
timeout: 5s
retries: 10
app:
image: myapp:latest # или build: . — если собирать из Dockerfile
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/myapp
SPRING_DATASOURCE_USERNAME: myapp
SPRING_DATASOURCE_PASSWORD: secret
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy # ждём, пока Postgres не пройдёт healthcheck
volumes:
postgres_data:
Разберём ключевые блоки.
services
services — главный раздел файла. Каждый ключ внутри — имя сервиса (db, app). Это имя одновременно является именем хоста внутри сети Compose: из контейнера app можно обратиться к базе данных просто по имени db. Никаких IP-адресов прописывать не нужно — Compose создаёт внутреннюю DNS-запись автоматически.
image и build
image указывает, какой образ использовать. Если образ ещё нужно собрать из Dockerfile, используйте build: . вместо image (или вместе с ним для задания имени тега). Для приложения при разработке часто удобнее собирать образ налету:
app:
build:
context: .
dockerfile: Dockerfile
environment
environment задаёт переменные окружения внутри контейнера. Spring Boot читает переменные окружения и использует их как свойства конфигурации: SPRING_DATASOURCE_URL соответствует spring.datasource.url в application.properties.
Длинный список переменных удобно выносить в файл .env и ссылаться на него через env_file: .env.
ports
ports пробрасывает порт из контейнера на хост. Формат "хост:контейнер". Если вам не нужен доступ к Postgres с хоста (только из приложения внутри сети Compose), блок ports для базы можно убрать — контейнеры всё равно видят друг друга по имени сервиса.
volumes
volumes в секции сервиса монтирует том или директорию хоста внутрь контейнера. В примере выше именованный том postgres_data хранит данные Postgres между перезапусками. Именованные тома объявляются в разделе volumes верхнего уровня.
Для разработки удобно монтировать директорию с кодом:
volumes:
- ./src:/app/src # изменения в коде сразу видны в контейнере
healthcheck
healthcheck задаёт команду проверки готовности сервиса. Compose периодически запускает её внутри контейнера и отмечает сервис как healthy только после успешного прохождения.
Без healthcheck зависимость depends_on срабатывает, когда контейнер запущен, но Postgres ещё не принимает соединения — приложение упадёт с ошибкой подключения. С healthcheck и condition: service_healthy Compose дождётся реальной готовности базы.
depends_on
depends_on управляет порядком запуска. В простейшем виде:
depends_on:
- db
Но это только гарантирует, что контейнер db запущен раньше app. Для гарантии готовности используйте расширенный вариант с condition:
depends_on:
db:
condition: service_healthy
Основные команды
# запустить все сервисы в фоне
docker compose up -d
# посмотреть логи всех сервисов (или конкретного: ... logs db)
docker compose logs -f
# остановить и удалить контейнеры (тома сохраняются)
docker compose down
# остановить и удалить контейнеры вместе с томами
docker compose down -v
# пересобрать образ и перезапустить
docker compose up -d --build
# выполнить команду внутри запущенного контейнера
docker compose exec db psql -U myapp
Сети в Compose
По умолчанию Compose создаёт одну общую сеть для всех сервисов файла. Все контейнеры в этой сети видят друг друга по именам сервисов. Вы можете явно описывать несколько сетей — например, чтобы изолировать часть сервисов:
services:
app:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:
Подробнее о сетях — в статье Сети в Docker.
Пример: Spring Boot + Postgres с профилем разработки
Полный docker-compose.yml для локальной разработки Spring Boot приложения:
services:
db:
image: postgres:16
environment:
POSTGRES_DB: orders
POSTGRES_USER: orders
POSTGRES_PASSWORD: dev_secret
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U orders"]
interval: 5s
retries: 10
app:
build: .
environment:
SPRING_PROFILES_ACTIVE: dev
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/orders
SPRING_DATASOURCE_USERNAME: orders
SPRING_DATASOURCE_PASSWORD: dev_secret
SPRING_JPA_HIBERNATE_DDL_AUTO: validate
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy
volumes:
- ~/.m2:/root/.m2 # кэш Maven между перезапусками сборки
volumes:
pg_data:
Команда docker compose up -d поднимет Postgres, дождётся его готовности и только потом запустит приложение. Логи обоих контейнеров будут доступны через docker compose logs -f.
Коротко
- Docker Compose описывает многоконтейнерное окружение в одном YAML-файле и запускает его одной командой.
- Сервисы видят друг друга по именам, заданным в
services:— DNS-резолюция работает автоматически. healthcheck+depends_on: condition: service_healthyгарантируют, что зависимый сервис стартует после реальной готовности базы.volumesсохраняют данные между перезапусками контейнеров.environmentпередаёт конфигурацию — Spring Boot читает переменные окружения напрямую как свойства.docker compose downостанавливает и удаляет контейнеры, тома при этом сохраняются;down -vудаляет и тома.- Файл
docker-compose.ymlкоммитится в репозиторий — окружение воспроизводимо на любой машине.
Что почитать дальше
- Сети в Docker — как устроены сети между контейнерами, как их изолировать.
- Тома и хранение данных — типы томов, bind mounts, когда что использовать.
- Запуск контейнеров — флаги
docker run, управление жизненным циклом контейнера.