alltools.one
DevOps
2025-06-16
8 min
alltools.one Team
YAMLDockerDocker ComposeDevOpsContainers

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 в том, что ваша конфигурация разработки напрямую информирует продакшен, уменьшая различия сред.

Связанные ресурсы

Published on 2025-06-16
YAML for Docker Compose: Configuration Patterns and Tips | alltools.one