Коли compose.yaml росте до десятків сервісів, з'являються дублювання й конфлікти. Compose має кілька механізмів структурування.
1. include (Compose 2.20+) - підключити інший файл Compose як окремий підпроєкт зі своїми відносними шляхами:
# compose.yaml
include:
- infra/compose.yaml # бази, Redis, пошук
- path: tools/compose.yaml # інструменти розробки
env_file: tools/.env
services:
app:
build: .
depends_on: [postgres, redis] # сервіси з підключених файлів доступні
На відміну від злиття через -f, кожен підключений файл розв'язує шляхи відносно свого розташування, тож команда, що відповідає за інфраструктуру, може тримати свій файл окремо. Конфлікт імен сервісів - помилка, а не тихе злиття.
2. extends - успадкувати конфігурацію сервісу з того самого чи іншого файлу:
services:
php-base:
build: .
environment:
APP_ENV: local
volumes:
- .:/var/www/html
app:
extends: php-base
ports: ["127.0.0.1:8000:8000"]
worker:
extends: php-base
command: php artisan queue:work
scheduler:
extends: php-base
command: php artisan schedule:work
3. Якорі YAML і поля розширення x-:
x-php: &php
build: .
env_file: .env
volumes: [".:/var/www/html"]
services:
app:
<<: *php
ports: ["127.0.0.1:8000:8000"]
worker:
<<: *php
command: php artisan queue:work
Поля верхнього рівня з префіксом x- Compose ігнорує, тож туди зручно класти спільні фрагменти. Злиття <<: - поверхневе: вкладені словники заміняються повністю, а не зливаються.
Як обрати:
- кілька незалежних частин (інфраструктура, застосунок, інструменти), різні власники -
include; - кілька ролей одного образу (web, worker, scheduler) -
extendsчи якорі YAML; - різні оточення для тих самих сервісів - кілька файлів через
-fчи профілі.
Перевірка результату - завжди docker compose config: усі три механізми розгортаються в підсумкову конфігурацію, і саме її варто перевіряти, а не покладатися на уявлення про злиття.