YAML для Docker Compose: паттерны конфигурации и советы
Docker Compose использует YAML для описания многоконтейнерных приложений. Хорошо структурированный docker-compose.yml — это разница между плавно работающей средой разработки и часами отладки контейнерных проблем. Это руководство охватывает основные паттерны и распространённые подводные камни.
Базовая структура
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- api
api:
build: ./api
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://db:5432/myapp
depends_on:
- db
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: secret
volumes:
pgdata:
Переменные окружения
Встроенные
services:
api:
environment:
NODE_ENV: production
PORT: "3000"
DEBUG: "false"
Из файла
services:
api:
env_file:
- .env
- .env.local # Переопределяет значения .env
Подстановка переменных
Ссылки на переменные окружения хоста:
services:
api:
image: myapp:${TAG:-latest} # По умолчанию "latest"
environment:
API_KEY: ${API_KEY} # Обязательная — ошибка, если не задана
LOG_LEVEL: ${LOG_LEVEL:-info} # По умолчанию "info"
Сети
Пользовательские сети
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:
internal: true # Без внешнего доступа
Сервисы в одной сети могут обращаться друг к другу по имени сервиса. Сервис db доступен только из api, но не из web.
Маппинг портов
ports:
- "8080:80" # host:container
- "443:443"
- "127.0.0.1:3000:3000" # Привязка только к localhost
- "3000" # Случайный порт хоста
Тома
Именованные тома (постоянные)
services:
db:
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
driver: local
Привязки каталогов (разработка)
services:
api:
volumes:
- ./src:/app/src # Исходный код
- /app/node_modules # Анонимный том (предотвращает перезапись)
Паттерн с анонимным томом (/app/node_modules) предотвращает перезапись зависимостей, установленных в контейнере, привязкой каталога хоста.
Проверки здоровья
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
api:
depends_on:
db:
condition: service_healthy
Это гарантирует, что api запустится только после того, как db пройдёт проверку здоровья, а не просто после запуска контейнера.
Поля расширения (DRY-паттерны)
Используйте поля с префиксом x- и якоря YAML для уменьшения повторений:
x-common: &common
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
x-env: &common-env
TZ: UTC
LOG_FORMAT: json
services:
api:
<<: *common
build: ./api
environment:
<<: *common-env
PORT: "3000"
worker:
<<: *common
build: ./worker
environment:
<<: *common-env
QUEUE: default
Подробнее о якорях YAML читайте в нашем руководстве по якорям и псевдонимам YAML.
Многоэтапный Compose
Разработка vs продакшен
# docker-compose.yml (базовый)
services:
api:
build: ./api
environment:
DATABASE_URL: postgres://db:5432/myapp
# docker-compose.override.yml (dev — загружается автоматически)
services:
api:
volumes:
- ./api/src:/app/src
environment:
NODE_ENV: development
DEBUG: "true"
ports:
- "3000:3000"
- "9229:9229" # Debug port
# docker-compose.prod.yml
services:
api:
environment:
NODE_ENV: production
deploy:
replicas: 3
# Development (auto-loads override)
docker compose up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
Распространённые ошибки
1. Незакавыченные номера портов
# РИСКОВАННО — YAML интерпретирует 80:80 как число в шестидесятеричной системе
ports:
- 80:80
# БЕЗОПАСНО — всегда используйте кавычки
ports:
- "80:80"
2. Логические переменные окружения
# НЕПРАВИЛЬНО — YAML конвертирует в boolean
environment:
DEBUG: true # Становится Python True, а не строка "true"
# ПРАВИЛЬНО — заключайте все значения env в кавычки
environment:
DEBUG: "true"
3. Тайминг depends_on
depends_on ожидает только запуска контейнера, а не его готовности:
# Контейнер запущен, но БД может быть не готова
depends_on:
- db
# Ожидание проверки здоровья
depends_on:
db:
condition: service_healthy
Проверяйте файлы Docker Compose с помощью нашего YAML Validator.
Часто задаваемые вопросы
В чём разница между docker-compose.yml и compose.yml?
Оба имени файлов работают. compose.yml — это более новое соглашение, рекомендованное Docker. docker-compose.yml — устаревшее имя. Docker Compose v2+ ищет оба файла, отдавая предпочтение compose.yml, если оба существуют. Для новых проектов используйте compose.yml.
Стоит ли использовать Docker Compose в продакшене?
Docker Compose отлично подходит для разработки и простых деплоев. Для продакшена в масштабе рассмотрите Docker Swarm (нативно использует файлы Compose) или Kubernetes. Преимущество Compose в том, что ваша конфигурация разработки напрямую информирует продакшен, уменьшая различия сред.
Связанные ресурсы
- YAML Validator — валидация Docker Compose YAML
- Якоря и псевдонимы YAML — паттерны DRY-конфигурации
- Учебник по синтаксису YAML — основы YAML