Docker Compose — это инструмент для описания и запуска многоконтейнерных приложений с помощью единого конфигурационного файла (обычно docker-compose.yml). Он упрощает работу с сервисами, которые зависят друг от друга, например: веб-приложение, база данных, кеш и очередь сообщений.
Основная идея
Вместо того чтобы вручную запускать каждый контейнер и связывать их сетью и томами, вы описываете всю инфраструктуру приложения в YAML-файле:
- Сервисы (services) — отдельные контейнеры с указанием образа или
Dockerfile. - Сети (networks) — как контейнеры будут общаться друг с другом.
- Тома (volumes) — куда сохраняются данные.
- Переменные окружения (environment) — настройки для каждого сервиса.
- Порты (ports) — маппинг между хостом и контейнером.
Пример конфигурации
version: "3.9"
services:
app:
build: .
ports:
- "8080:8080"
environment:
DB_HOST: db
DB_USER: appuser
depends_on:
- db
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: secret
POSTGRES_DB: appdb
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Ключевые возможности
- Быстрый запуск окружений
docker compose up -d— и всё приложение поднимается за один шаг. - Локальная разработка
Легко эмулировать продакшн-среду у каждого разработчика. - Версионирование конфигурации
Файлdocker-compose.ymlхранится в Git, что делает конфигурацию воспроизводимой. - Изоляция окружений
Каждое окружение (dev, test, stage) может иметь свой compose-файл или override.
Практические приёмы
- Override-файлы (
docker-compose.override.yml) — для настройки параметров в dev-режиме (маппинг исходников, hot-reload). - .env файл — вынос чувствительных данных и параметров окружения.
- Профили (profiles) — запуск только нужных сервисов (
docker compose --profile debug up). - Мульти-stage build в связке с Compose для оптимизации образов.
- Поддержка нескольких файлов:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
Интеграция с другими инструментами
- Docker Swarm — можно масштабировать сервисы на нескольких узлах с теми же конфигами.
- CI/CD — автоматический запуск Compose-окружения для тестов.
- Kubernetes — через утилиты типа Kompose можно конвертировать
docker-compose.ymlв манифесты K8s.
Безопасность и удобство
- Не храните пароли прямо в YAML — используйте
.envили секреты (docker secrets). - Для production лучше разделять образы и конфиги, избегая dev-инструментов в рантайме.
- Мониторьте версии образов и регулярно пересобирайте сервисы.
Для чего это клиенту
Compose делает инфраструктуру приложения прозрачной, воспроизводимой и управляемой. Клиент или команда разработки получают среду, которую можно поднять на любом компьютере или сервере за минуты, без «сюрпризов» в настройках. Это сокращает время на развёртывание, упрощает онбординг новых сотрудников и минимизирует человеческий фактор.
Вот компактный продакшн‑шаблон docker-compose.yml с практичными настройками безопасности, логирования, healthcheck, ограничениями ресурсов и разделением конфигурации. Подойдёт как базис для большинства веб‑приложений (web + db + reverse‑proxy).
version: "3.9"
x-common-env: &common_env
TZ: "UTC"
APP_ENV: "production"
# секреты/пароли — через .env или secrets, а не в YAML
x-common-deploy: &common_deploy
restart: always
# Ограничения ресурсов (примерные значения — подберите по нагрузке)
deploy:
resources:
limits:
cpus: "1.0"
memory: "512M"
reservations:
cpus: "0.25"
memory: "256M"
networks:
edge:
driver: bridge
backend:
driver: bridge
internal: true # недоступна извне хоста
volumes:
db_data:
caddy_data: # для certmagic (автосертификаты)
caddy_config:
secrets:
db_password:
file: ./secrets/db_password.txt
services:
reverse-proxy:
image: caddy:2.8
command: caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
ports:
- "80:80"
- "443:443"
environment:
<<: *common_env
volumes:
- ./ops/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
- web
networks:
- edge
- backend
<<: *common_deploy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://web:8080/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
web:
build:
context: .
dockerfile: Dockerfile
target: runtime # используйте multi-stage build
environment:
<<: *common_env
DATABASE_HOST: db
DATABASE_USER: app_user
DATABASE_PASSWORD_FILE: /run/secrets/db_password
DATABASE_NAME: app
# Логирование
LOG_LEVEL: info
secrets:
- db_password
expose:
- "8080" # видим только в сети backend
depends_on:
db:
condition: service_healthy
networks:
- backend
<<: *common_deploy
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
interval: 20s
timeout: 3s
retries: 5
db:
image: postgres:16-alpine
environment:
<<: *common_env
POSTGRES_DB: app
POSTGRES_USER: app_user
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
# Безопасные дефолты: отключите авто‑создание экстеншенов, ограничьте локали и т.п. — по нужде
secrets:
- db_password
volumes:
- db_data:/var/lib/postgresql/data
expose:
- "5432" # только в backend
networks:
- backend
<<: *common_deploy
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app_user -d app -h localhost"]
interval: 15s
timeout: 5s
retries: 5
# Доп. защита: read_only & tmpfs (сложно с БД, используйте на stateless-сервисах)
Файл ops/caddy/Caddyfile (пример с автоматическим TLS и проксированием)
example.com, www.example.com {
encode zstd gzip
log {
output stdout
format json
}
handle_path /health {
respond 200
}
reverse_proxy web:8080 {
health_uri /health
trusted_proxies 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
}
# базовые заголовки безопасности
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
Referrer-Policy "no-referrer"
X-Frame-Options "DENY"
}
}
Рекомендации к продакшн‑использованию
- Секреты: храните в
./secrets/…, доступ ограничьте правами ОС. Для облака — лучше менеджер секретов (AWS/GCP/Azure). - .env: выносите не чувствительные параметры (порты, флаги фич). Не лепите туда пароли.
- Образы: используйте multi‑stage builds, distroless/‑slim; запускайте процесс от непривилегированного пользователя (
USER). - Логи: JSON‑формат; централизуйте сбор (ELK/Vector/Loki) через драйверы логирования или sidecar/агенты.
- Здоровье: поддерживайте реальные
health‑эндпойнты на web; для БД —pg_isready/mysqladmin ping. - Сети: внешние порты открывайте только на reverse‑proxy. Внутренние сервисы держите в
internalсети. - Резервирование: бэкапы БД вне контейнера, регулярные тесты восстановления (backup verification).
- Обновления: пересобирайте образы на патчи базового слоя; фиксируйте версии и используйте digest (
image@sha256:…). - Безопасность: включайте
readonlyиtmpfsдля stateless‑сервисов,no-new-privileges,cap_drop: ["ALL"](где возможно).