docker.yml / docker.local.yml
Политика выполнения Compose для dwe-проекта.
Содержание
Заголовок раздела «Содержание»- Назначение
- dwe docker vs dwe compose
- Структура
- Справочник полей
- docker.local.yml
- Частые ловушки
- Связанные команды
Назначение
Заголовок раздела «Назначение»workspace/docker.yml определяет, как dwe docker собирает и выполняет команды docker compose: имя проекта, args для каждой подкоманды и process environment. Файл .env автоматически регенерируется CLI до {up, run, exec, restart, build} — это поведение не настраивается.
Файл загружается отдельно и не участвует в трёхслойном мердже.
Локальные переопределения кладутся в workspace/docker.local.yml (gitignored). Шаблон — в workspace/docker.local.example.yml. Локальные переопределения глубоко мержатся в docker.yml до распаковки — local выигрывает при конфликте ключей, списки заменяются.
flowchart LR
A["workspace/docker.yml"] --> M(["deepMerge"])
B["workspace/docker.local.yml<br/>optional, gitignored"] --> M
M --> P(["resolveVarTemplate<br/>$#123;...#125; against DweConfig.Raw"])
P --> R[("DockerConfig")]
dwe docker vs dwe compose
Заголовок раздела «dwe docker vs dwe compose»| Команда | Назначение |
|---|---|
dwe docker <subcommand> | Публичный lifecycle API. Применяются policy-args. Используйте в Makefile’ах, шагах деплоя и YAML-командах. |
dwe compose raw <args...> | Низкоуровневая диагностическая прокидка. Без policy-args. Используйте только для отладки. |
dwe compose files | Показать список активных compose-файлов (диагностика). |
dwe compose argv | Показать полный итоговый argv, включая policy-args (диагностика). |
В Makefile’ах, декларациях YAML-команд и шагах деплоя разрешены только подкоманды dwe docker. Прямые вызовы docker compose обходят политику и не должны появляться ни в какой автоматизации.
Структура
Заголовок раздела «Структура»project_name: "${project.prefix}-${project.name}"
args: global: ["--ansi", "always", "--progress", "tty"] up: ["-d", "--remove-orphans"] logs: ["-f"] run: ["--rm"] pull: [] build: []
process_env: DOCKER_CLI_HINTS: "false"
topology: hidden: [redis-insight-setup]
resources: volumes: composer_cache: name: dwe_composer_cache shared: true ensure_before: [up, deploy]
build: prepull_bases: falseСправочник полей
Заголовок раздела «Справочник полей»project_name
Заголовок раздела «project_name»project_name: "${project.prefix}-${project.name}"Имя Docker Compose-проекта, передаваемое как -p <name> в каждый compose-вызов. Поддерживает ${dot.path} lookup’ы по смерженному DWE-конфигу (см. Шаблоны — пространства имён ${...}), разрешаемый по отдельному, более строгому правилу: любой dot-path в Raw резолвится здесь (без whitelist’а по неймспейсам), но неразрешённый путь — это жёсткая ошибка, а не буквальный ${...} — сломанное имя проекта должно упасть громко, а не молча дойти как ${...} до docker compose -p. По умолчанию разрешается в dwe-laravel.
Итоговое имя приводится к нижнему регистру. Docker Compose требует имя проекта, соответствующее [a-z0-9][a-z0-9_-]*, и отвергает верхний регистр, тогда как project.name, project.prefix и это поле — свободный пользовательский текст: project.name: cueBreaker разрешается в dwe-cuebreaker, а project_name: "MyApp" — в myapp. Именно эта форма попадает в docker compose -p, печатается dwe docker project-name и лежит в основе всех производных имён: имён контейнеров (<project>-<service>), префикса непошаренных томов <project_name>_ и фильтра по метке com.docker.compose.project, которым пользуются статус, посервисные stop/restart и reset. Проект, ранее работавший под именем с заглавными буквами, стоит сначала остановить прежней версией dwe — compose считает старые контейнеры и тома принадлежащими другому проекту, иначе они останутся висеть.
Локальное переопределение:
project_name: "my-custom-project"Списки args для каждой подкоманды. Каждый ключ — это имя docker-подкоманды; global применяется к каждому вызову перед args, специфичными для подкоманды.
args: global: ["--ansi", "always", "--progress", "tty"] up: ["-d", "--remove-orphans"] logs: ["-f"] run: ["--rm"] pull: ["--policy", "always"] build: ["--progress", "plain"]Доступные ключи подкоманд: global, up, down, stop, restart, logs, ps, exec, run, pull, build. (Health-чеки контейнеров используют билтин docker_wait_healthy в шагах пайплайна, настраиваемый параметрами timeout и interval.)
Дефолты на ключ:
Четыре подкоманды имеют встроенные дефолты, применяемые автоматически, когда ключ отсутствует и в docker.yml, и в docker.local.yml:
| Ключ | По умолчанию |
|---|---|
up | ["-d", "--remove-orphans"] |
logs | ["-f"] |
run | ["--rm"] |
down | ["--remove-orphans"] |
Другие ключи (global, stop, restart, ps, exec, pull, build) дефолтов не имеют — они nil, если отсутствуют, пустые, если явно [], и заполнены, если явно заданы.
Nil vs. явный empty:
Дефолты применяются только когда ключ отсутствует в YAML-источнике. Явный пустой список (key: []) отменяет дефолт:
# Отсутствующий ключ up → используется дефолт [-d, --remove-orphans]args: logs: [] # Явный empty → дефолт не применяется, остаётся []
# Явный up → используется указанное значение, без слияния с дефолтомargs: up: ["--no-deps"] # Заменяет дефолт, без слиянияПри переопределении в docker.local.yml список заменяет отслеживаемый дефолт целиком (списки не сливаются):
# docker.local.yml — убрать --progress tty (не поддерживается некоторыми терминалами)args: global: ["--ansi", "always"] # up, logs, run, down не указаны → дефолты по-прежнему применяются из docker.yml или встроенныеПодкоманды управления образами (pull и build)
Подкоманды pull и build включают опциональные флаги для контроля набора файлов и поведения кеша:
-
dwe docker pull [--all] [services...]— притянуть образы для сервисов. По умолчанию использует активный набор compose-файлов (base + включённые оверлеи). Флаг--allтянет образы по всем настроенным оверлеям, независимо от локального состояния enable, без правкиworkspace/local.yml. -
dwe docker build [--all] [--force] [services...]— собрать образы для сервисов. По умолчанию ведёт себя так же, как pull. Флаг--forceдописывает--no-cache --pullдля обхода layer-кеша Docker и повторного pull базовых слоёв.--allи--forceможно комбинировать.
Если args.pull или args.build заданы, они применяются перед позиционными сервисами или force-флагами. Пример:
args: pull: ["--policy", "always"] build: ["--progress", "plain"]Флаг --all — это переопределение только на один вызов: он НЕ изменяет workspace/local.yml и не сохраняется между командами.
process_env
Заголовок раздела «process_env»Переменные окружения, передаваемые в каждый дочерний процесс docker compose. Не влияет на окружение контейнера — только на сам процесс CLI compose.
process_env: DOCKER_CLI_HINTS: "false"Полезно, чтобы подавить шум Docker CLI, появляющийся даже когда вывод направляется в пайп.
topology
Заголовок раздела «topology»topology: hidden: [redis-insight-setup]| Поле | Описание |
|---|---|
hidden | Имена compose-сервисов, исключаемые из дерева топологии и health-чеков |
Полезно для init-контейнеров, которые отрабатывают один раз и выходят — скрытие не даёт билтину docker_wait_healthy их ждать.
resources
Заголовок раздела «resources»Объявляет Docker-ресурсы, которые должны существовать перед определёнными командами.
resources: volumes: composer_cache: name: dwe_composer_cache shared: true ensure_before: [up, deploy]| Поле | Описание |
|---|---|
volumes.<key>.name | Базовое имя тома. Реальное имя в Docker зависит от shared: shared-тома используют name как есть (пишите туда полное литеральное имя — префикс не применяется); non-shared тома сохраняются как <project_name>_<name>, чтобы разделять жизненный цикл и область действия с compose-проектом (соответствуя соглашению Docker Compose для именованных томов, объявленных внутри compose.yaml). |
volumes.<key>.shared | Если true, том независим от проекта: реальное имя в Docker равно name, и том переживает project reset’ы. Если false (по умолчанию), том привязан к проекту — runtime добавляет префикс <project_name>_, и docker_remove_project_volumes (reset-билтин) удаляет его вместе с проектом. Здесь <project_name> — разрешённое имя compose-проекта: project_name из этого файла, если задан, иначе дефолт <prefix>-<name> — так что non-shared тома получают префикс единообразно даже когда project_name опущен. |
volumes.<key>.ensure_before | Триггеры, идемпотентно создающие том при его отсутствии. Поддерживаемые значения: up, deploy. |
resources: volumes: composer_cache: # логический ключ name: dwe_composer_cache # реальное имя в Docker (shared) shared: true ensure_before: [up, deploy]
build_artifacts: # реальное имя в Docker = "<project_name>_build_artifacts" name: build_artifacts ensure_before: [deploy]docker_remove_project_volumes (reset-билтин) удаляет каждый том, имя которого начинается с <project_name>_, поэтому non-shared тома сбрасываются вместе с проектом, а shared-тома выживают.
build: prepull_bases: false| Поле | Описание |
|---|---|
prepull_bases | Если true, dwe docker build и dwe docker up вычисляют внешние базовые образы FROM, используемые собираемыми сервисами, и выполняют docker pull для тех, что отсутствуют в локальном хранилище образов, до передачи управления compose build/compose up. По умолчанию false. |
Зачем это нужно: buildkit-фетчер Docker Desktop не всегда может достучаться до LAN/приватных registry (failed to fetch oauth token … no route to host), хотя обычный docker pull на стороне демона достаёт их без проблем. buildkit в docker-драйвере разделяет хранилище образов с демоном, поэтому если базовый образ FROM уже есть локально, buildkit разрешает его без обращения к сети. prepull_bases обходит проблему фетчера, заранее наполняя хранилище через docker pull — ровно для тех базовых образов, которые нужны сборке.
Покрытие: покрываются и dwe docker build [services...], и dwe docker up — up тоже собирает образы, отсутствующие в хранилище, а дефолтный пайплайн деплоя/lifecycle запускает dwe docker up --wait, поэтому первый деплой на чистой машине выигрывает без дополнительной настройки. build сужает вычисление до указанных сервисов (или всех, без аргументов); up всегда вычисляет базовые образы по всем сервисам активного compose-конфига, поскольку up собирает зависимости транзитивно.
По умолчанию тянутся только отсутствующие образы: уже присутствующий локально базовый образ никогда не перетягивается повторно — это устраняет именно случай «базового образа нет локально», не меняя семантику «закешированный базовый образ не обновляется».
Взаимодействие с --force: при выключенном флаге dwe docker build --force ведёт себя точно так же, как раньше — compose получает --no-cache --pull. При включённом флаге --force вместо этого безусловно тянет все вычисленные базовые образы через демон, а compose получает только --no-cache (без --pull) — собственный --pull у buildkit упирается в ту же проблему фетча LAN-registry, поэтому повторный pull на стороне демона — единственный надёжный путь «обновить базовые образы» при включённом флаге.
Advisory-поведение, никогда не жёсткий сбой: каждый шаг prepull (вычисление ссылок из compose config и Dockerfile’ов сервисов, проверка наличия базового образа локально, pull) выполняется по принципу best-effort, и обычные compose build/compose up всегда выполняются после него — включение prepull_bases не может сделать сборку хуже, чем без него. В stderr попадает лишь узкий набор случаев:
- Сбой вычисления (падает вызов
compose configлибо его JSON-вывод не удаётся разобрать) → одноwarning:с описанием сбоя; prepull пропускается, сборка продолжается. Отдельный нечитаемый или неразбираемый Dockerfile сервиса — это не сбой вычисления: такой сервис пропускается молча (видно только под--debug), а базовые образы остальных сервисов всё равно пуллятся. - Сбой пробы наличия образа (нет бинарника, недоступен демон,
inspectбез поддержки--platform) трактуется как «отсутствует» и молча запускает pull — без предупреждения; ценой становится лишь лишний, но безвредный pull. - Успешный pull — молча.
- Неудавшийся pull →
warning:. Если образ был подтверждённо отсутствующим, сообщается, что сборка, скорее всего, провалится (сбой теперь предсказуем); если это был--force-перетягивание уже присутствующего образа — это более мягкое уведомление, и используется закешированный образ.
docker.local.yml
Заголовок раздела «docker.local.yml»Локальные переопределения для политики docker. Gitignored. Используйте workspace/docker.local.example.yml как стартовый шаблон.
docker.local.ymlvslocal.yml → compose.extra. Для политики выполнения compose (имя проекта, аргументы подкоманд, окружение процесса) →docker.local.yml(этот файл). Для оверлеев сервисов в compose (дополнительные-f-файлы, вкатывающие env-переменные, тома, порты в контейнерах) →compose.extra/services.<name>.compose.extraвlocal.yml. Это независимые поверхности — см.workspace.md.
Распространённые переопределения:
# Переопределить имя проектаproject_name: "personal-laravel"
# Убрать --progress tty (не поддерживается некоторыми терминалами)args: global: ["--ansi", "always"]
# Подавить Docker-подсказкиprocess_env: DOCKER_CLI_HINTS: "false"Частые ловушки
Заголовок раздела «Частые ловушки»- Прямые
docker composeв Makefile’ах или YAML — всегда используйтеdwe docker. Прямые вызовы обходят policy-args, имя проекта и авто-генерацию.env. - Добавление compose-флагов в Make-рецептах — флаги должны быть в секции args в
docker.yml, а не в Make. Lifecycle-таргеты Make вызываютdwe dockerбез флагов. - Частичное переопределение args —
args.upвdocker.local.ymlзаменяет отслеживаемый список, а не дописывает к нему. Указывайте все нужные флаги. - Расчёт на пре-генерацию
.envв CI —.envвсегда регенерируется перед{up, run, exec, restart, build}, и это нельзя отключить (см. Назначение). Любой пре-генерированный.envбудет перезаписан; конфигурационного переключателя для этого нет.
Связанные команды
Заголовок раздела «Связанные команды»dwe docker up|down|stop|restart|logs|ps|exec|run|pull|build— команды lifecycle и управления образами (upпринимает--wait, чтобы блокироваться до готовности сервисов)dwe compose files— показать список активных compose-файловdwe compose argv— показать полный итоговый argvdwe render env— вручную регенерировать.env