ONBUILD в Docker: триггеры для базовых образов

Быстрые ссылки
- Добавление триггеров ONBUILD
- Как Docker распознаёт триггеры?
- Ограничения
- Когда полезны ONBUILD
- Практическое руководство и чеклист
- Примеры и контрпримеры
- Безопасность и миграция
- Критерии приёмки
- Резюме
Что такое ONBUILD (одно предложение)
ONBUILD — это инструкция Dockerfile, которая принимает другую инструкцию в качестве аргумента и откладывает её выполнение до момента, когда образ будет использован как базовый для другого Dockerfile.
Добавление триггеров ONBUILD
Инструкция ONBUILD записывается прямо в Dockerfile и принимает в качестве аргумента любую поддерживаемую Docker-инструкцию (за исключениями, описанными ниже). Примеры:
ONBUILD RUN example-commandЭтот пример выполнит example-command в дочернем образе при его сборке. Другой пример — копирование файла из build-контекста downstream-образа в файловую систему образа:
ONBUILD COPY assets.json /app/assets.jsonВажно: ONBUILD не влияет на сам образ, в котором он определён. Сборка Dockerfile с такими инструкциями не выполнит отложенные команды и не добавит соответствующие файлы в создаваемый образ.
Пример сборки базового образа:
docker build -t base-image:latest .Триггеры вступают в силу, когда вы используете созданный образ как базу в другом Dockerfile:
FROM base-image:latest
RUN my-binarydocker build -t downstream-image:latest .При сборке downstream-image сначала выполнится набор ONBUILD-инструкций из base-image, затем последует RUN my-binary. ONBUILD-инструкции всегда выполняются сразу после FROM в дочернем Dockerfile и в том порядке, в каком они были записаны в исходном Dockerfile.
Как Docker распознаёт триггеры?
Docker хранит ONBUILD-инструкции в метаданных образа. При разборе Dockerfile с инструкцией FROM движок проверяет метаданные указанного образа. Если в них есть отложенные триггеры, Docker временно добавляет эти инструкции в начало текущего Dockerfile перед продолжением сборки.
Триггеры выполняются как часть этапа FROM. Если одна из ONBUILD-инструкций завершится с ошибкой, сборка прервётся и ошибка будет выглядеть как ошибка на этапе FROM.
Ограничения
Вы можете подставить любую Docker-инструкцию в ONBUILD, кроме трёх исключений:
- ONBUILD FROM — нельзя, потому что это подменит базовый образ. Каждый Dockerfile наследует ровно от одного базового образа.
- ONBUILD MAINTAINER — deprecated; информацию об авторстве лучше указывать через LABEL.
- ONBUILD ONBUILD — нельзя вкладывать ONBUILD в ONBUILD. Триггеры выполняются только на один уровень вниз; вы не можете определить инструкции, которые должны выполниться в «внуках» образа.
Все инструкции формулируются так же, как и в обычном Dockerfile — просто добавьте префикс ONBUILD, чтобы переместить шаг из нормального потока в набор отложенных действий.
Когда полезны ONBUILD
ONBUILD особенно полезен для образов-утилит, предназначенных для автоматизации задач: компиляции кода, подготовки окружения, сборки артефактов. Сценарии, где ONBUILD оправдан:
- Образ предоставляет заранее настроенный инструмент (компилятор, сборщик), который ожидает исходники в известной директории.
- Нужно гарантировать последовательность шагов: сначала добавляются исходники, затем запускается сборка.
- Вы хотите скрыть boilerplate-инструкции от конечного пользователя, чтобы он писал короткий Dockerfile с указанием FROM и минимальным набором инструкций.
Пример шаблона билдера:
ENV BUILD_ENV=production
RUN init-build.sh
ONBUILD COPY /src /build
ONBUILD RUN compile.sh --destination=/binКогда пользователь создаёт Dockerfile на основе этого образа и добавляет свои исходники в build-контекст, при сборке автоматически выполнится COPY и затем compile.sh.
Практическое руководство и чеклист
Рекомендованный процесс при создании базового образа с ONBUILD:
- Определите контракт образа: где ожидаются исходники, какие файлы должен предоставить пользователь, какие переменные окружения поддерживаются.
- Используйте LABEL для документирования контракта (версия, ожидания путей, пример использования).
- По возможности делайте ONBUILD-операции идемпотентными и безопасными при повторных запусках.
- Тестируйте образ, создавая downstream-пример и собирая его в изолированном контексте.
- Обновляйте документацию при изменении контракта; версионируйте образ.
Чеклист перед публикацией базового образа:
- Описан контракт (куда копировать файлы)
- Что делает каждый ONBUILD шаг — документировано
- Нет ONBUILD FROM / MAINTAINER / ONBUILD ONBUILD
- Есть пример downstream Dockerfile и тестовый build
- LABELs с контактной и версионной информацией
Роли и обязанности (коротко):
- Разработчик образа: описывает контракт, пишет ONBUILD, поддерживает тесты.
- Потребитель образа: следит за соответствием build-контекста контракту, тестирует интеграцию.
Примеры и контрпримеры
Пример: образ для компиляции Go-приложения
FROM golang:1.20
RUN mkdir /app
WORKDIR /app
ONBUILD COPY . /app
ONBUILD RUN go build -o /bin/app ./...Downstream Dockerfile пользователя:
FROM my-go-builder:latest
# исходники находятся в build-контексте
RUN /bin/app --versionКонтрпример — когда ONBUILD мешает пользователю:
- Если образ должен быть универсальным и не предполагать конкретную структуру исходников. В таком случае ONBUILD COPY может затереть важные файлы или привести к конфликтам путей.
- Если downstream-процесс должен контролировать порядок шагов (например, сначала выполнить миграции, затем билд) — зашитые ONBUILD-правила снижают гибкость.
Когда ONBUILD «не работает» или вреден:
- Несовместимые контексты: если downstream-пользователь ожидает иной layout или использует нестандартный build-контекст.
- Сложные CI/CD-пайплайны: если в пайплайне предполагается многократное переиспользование одного образа с разными стратегиями сборки, ONBUILD усложнит настройку.
Ментальные модели и эвристики
- Думайте об ONBUILD как о шаблоне с заполнителями. Он не выполняет работу заранее, а подставляет шаги в Dockerfile потомка.
- ONBUILD удобен, когда вы владеете контрактом downstream: определяете, какие файлы пользователи должны положить в контекст и когда.
- Избегайте ONBUILD для образов, которые предполагается использовать в самых разных сценариях.
Эвристика: используйте ONBUILD, если 70–80% ожидаемых downstream-пользователей применяют один и тот же, документированный workflow. Если число сценариев велико и разнородно, отказ от ONBUILD предпочтительнее.
План миграции и совместимость
Если вы поддерживаете образ с ONBUILD и хотите перейти к явным инструкциям (более гибкий подход):
- Выпустите новую версию образа без ONBUILD, с подробным README и примером Dockerfile.
- Поддерживайте старую версию (с ONBUILD) в течение переходного периода, помечая её как deprecated.
- Предоставьте скрипт или Makefile, который воспроизводит поведение ONBUILD (например, копирует файлы и запускает сборку) — это поможет потребителям быстро адаптироваться.
Безопасность и приватность
- ONBUILD COPY перенесёт файлы из build-контекста пользователя в сборочный контейнер. Это может непреднамеренно включить секреты, если пользователь кладёт их в контекст. Документируйте и рекомендуйте хранить секреты вне build-контекста (например, через build args, секреты CI/CD).
- Не полагайтесь на ONBUILD для выполнения верификаций безопасности — добавьте явные проверки в downstream-образ или CI.
Критерии приёмки
Чтобы считать образ с ONBUILD готовым к использованию в production-процессах, проверьте:
- Документация содержит пример downstream Dockerfile и описание контрактов путей.
- Автоматические тесты покрывают минимум один downstream-сценарий.
- Все ONBUILD-инструкции корректно выполняются и не оставляют промежуточных нежелательных артефактов.
- Нет запрещённых ONBUILD-инструкций (FROM, MAINTAINER, ONBUILD).
Тестовый кейс (пример):
- Создать чистый build-контекст с минимальным набором файлов, указанных в контракте.
- Выполнить docker build downstream и убедиться, что ONBUILD шаги прошли успешно.
- Проверить, что итоговый образ содержит ожидаемые артефакты и запускается.
Диагностика и отладка
- Ошибка на этапе FROM обычно означает, что одна из ONBUILD-инструкций завершилась с ошибкой. Посмотрите логи сборки, чтобы увидеть первую точную ошибку.
- Если ONBUILD COPY не находит файл, убедитесь, что файл присутствует в build-контексте при запуске docker build из каталога downstream.
- Для локальной отладки создавайте минимальный downstream-контекст и логируйте содержимое каталогов в ONBUILD RUN для проверки ожидаемых путей.
Decision flowchart
flowchart TD
A[Нужен ли унифицированный boilerplate?] -->|Да| B{Контракт стабилен?}
A -->|Нет| E[Не используйте ONBUILD]
B -->|Да| C[Реализовать ONBUILD в базовом образе]
B -->|Нет| D[Документируйте шаблоны и дайте примеры]
C --> F[Добавить тесты downstream]
D --> FРезюме
ONBUILD — удобный инструмент для создания переиспользуемых базовых образов и автоматизации типовых шагов сборки downstream-образов. Он экономит повторяющийся код и упрощает жизнь потребителям ваших образов. Однако ONBUILD накладывает контракт на downstream-пользователя и ограничивает гибкость. Применяйте его только там, где контракт ясен, хорошо документирован и протестирован.
Важно: документируйте все ожидания и предоставляйте пример downstream Dockerfile. Если ожидаемые сценарии разнообразны, рассмотрите альтернативы — скрипты и Makefile, образцы CI-шаблонов или явные инструкции в README.
Похожие материалы
Настройка внешнего вида Android: темы, лаунчеры, значки
Динамические маршруты в Next.js
Переустановить Microsoft Store в Windows 11
Как добавить шрифты в GIMP
Как загрузить приложения Microsoft Store без магазина