← Весь справочник

docker compose (файл)

Формат compose.yaml — сервисы, образы, порты, переменные, тома, сети, depends_on и healthcheck

Compose-файл (compose.yaml или docker-compose.yml) описывает несколько контейнеров, которые запускаются вместе: из какого образа, какие порты открыть, какие переменные и тома подключить, в каком порядке стартовать. docker compose up читает файл и поднимает всё описанное.

В песочнице Docker не установлен. Здесь можно писать и проверять сам файл: yamlschema compose файл сверяет его со схемой Compose Specification и печатает ошибки.

Синтаксис

services:
  имя_сервиса:
    image: образ:тег
    ключ: значение
volumes:
  имя_тома:
networks:
  имя_сети:

Все сервисы файла по умолчанию попадают в общую сеть, и имя сервиса служит DNS-именем: сервис app достучится до сервиса db по адресу db. Ключ version: в начале файла устарел и игнорируется.

Верхний уровень

КлючЧто задаёт
servicesконтейнеры — основная часть файла
volumesименованные тома (данные переживают пересоздание контейнеров)
networksсети; без них создаётся одна сеть default
secrets / configsфайлы, которые монтируются в контейнеры (/run/secrets/имя)
nameимя проекта (префикс контейнеров, томов, сетей)

Ключи сервиса

Образ и запуск

КлючЧто задаёт
imageобраз, например postgres:16
buildсобрать образ: build: . или context, dockerfile, args, target
commandзаменить команду образа (CMD); строкой или списком
entrypointзаменить ENTRYPOINT образа
container_nameфиксированное имя контейнера (тогда сервис нельзя масштабировать)
user, working_dirпользователь и рабочий каталог процесса
restartno (по умолчанию), always, on-failure, unless-stopped
profilesсервис стартует, только если профиль включён: --profile имя
initзапустить маленький init-процесс, который собирает зомби и передаёт сигналы

Сеть и порты

КлючЧто задаёт
portsпроброс на хост: "8080:80", "127.0.0.1:8080:80" (только локально), "53:53/udp"
exposeпорт виден другим сервисам, но не хосту (служит документацией)
networksк каким сетям подключить сервис
extra_hostsдополнительные записи в /etc/hosts контейнера

Переменные и данные

КлючЧто задаёт
environmentпеременные: словарём KEY: value или списком - KEY=value
env_fileфайл (или список файлов) со строками KEY=value
volumesимя_тома:/путь — том; ./каталог:/путь — каталог хоста; :ro — только чтение
tmpfsкаталоги в памяти
secretsкакие секреты верхнего уровня подключить

Порядок и здоровье

КлючЧто задаёт
depends_on: [db]короткая форма: стартовать после контейнера db
depends_on: {db: {condition: …}}длинная форма с условием (см. ниже)
healthcheck.testкоманда проверки: ["CMD", "прог", "арг"] или ["CMD-SHELL", "строка для sh"]
healthcheck.interval / timeout / retriesкак часто проверять / сколько ждать ответа / сколько неудач подряд считать «нездоров»
healthcheck.start_periodвремя на запуск, когда неудачи ещё не считаются
deploy.resources.limitsограничения cpus и memory
loggingдрайвер логов и его параметры (max-size)

Условия в depends_on:

conditionЖдать, пока зависимость…
service_startedзапустится (то же, что короткая форма)
service_healthyстанет healthy — нужен healthcheck у зависимости
service_completed_successfullyзавершится с кодом 0 (миграции, подготовка данных)

Подстановка переменных

В значениях можно ссылаться на переменные окружения и файла .env рядом с compose-файлом: ${TAG}, ${TAG:-latest} — значение по умолчанию, ${TAG:?нужно задать TAG} — ошибка, если переменной нет. $$ — буквальный $.

Команды (где установлен Docker)

КомандаЧто делает
docker compose up -dсоздать и запустить всё в фоне; --build — пересобрать образы
docker compose downостановить и удалить контейнеры и сети; -v — и тома
docker compose psсостояние сервисов
docker compose logs -f сервислоги, с ожиданием новых
docker compose exec сервис shоболочка в работающем контейнере
docker compose run --rm сервис командаодноразовый контейнер сервиса
docker compose configитоговый файл после подстановки переменных и проверки
docker compose restart / stop / pull / buildперезапуск / остановка / скачать / собрать образы

Примеры

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: example
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 10

  web:
    image: nginx:${NGINX_TAG:-1.27}
    ports:
      - "8080:80"
    volumes:
      - ./site:/usr/share/nginx/html:ro
    environment:
      - BACKEND_HOST=db
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

volumes:
  db-data:
# проверить файл по схеме (в песочнице)
yamlschema compose compose.yaml && echo OK

# опечатка в ключе даёт понятную ошибку, например:
# compose.yaml: services/web: Unevaluated properties are not allowed ('enviroment' was unexpected)

# посмотреть структуру файла: имена сервисов и их порты
yq '.services | keys' compose.yaml
yq '.services.web.ports' compose.yaml

# там, где есть Docker:
# docker compose config     # итоговый файл после подстановки переменных
# docker compose up -d      # поднять в фоне
# docker compose logs web   # логи одного сервиса
# docker compose down       # остановить и удалить контейнеры

Подводные камни

  • depends_on в короткой форме ждёт только старта контейнера, а не готовности программы внутри. База может ещё инициализироваться, когда приложение уже пытается подключиться. Чтобы ждать готовности, нужен healthcheck у зависимости и condition: service_healthy у зависимого сервиса.
  • depends_on влияет только на запуск через compose. Если зависимость упадёт позже, зависимый сервис об этом не узнает: приложение само должно уметь переподключаться.
  • Порты бери в кавычки. Некоторые YAML 1.1-парсеры читают 22:22 как число в шестидесятеричной записи (1342). Строка "22:22" однозначна.
  • Порядок в ports — хост:контейнер. "8080:80" открывает порт 8080 на хосте и ведёт его на 80 внутри контейнера, не наоборот. Без адреса порт слушается на всех интерфейсах хоста.
  • Именованный том нужно объявить в верхнеуровневом volumes:. Путь, начинающийся с ./ или /, — это каталог хоста, а не том.
  • Внутри сети используй имя сервиса и порт контейнера (db:5432), а не localhost и не порт хоста: localhost в контейнере — это сам контейнер.
  • environment важнее env_file. Если переменная задана в обоих местах, победит environment.
  • CMD и CMD-SHELL различаются. ["CMD", "pg_isready -U postgres"] ищет программу с пробелами в имени. Строку с аргументами передавай через CMD-SHELL или разбивай на элементы списка.
  • Схема ловит опечатки в ключах, но не смысл. yamlschema не проверит, объявлен ли том, допустимо ли значение restart, существует ли образ и свободен ли порт.

См. также

kubectl · yq · gitlab-ci · psql