Build icon
DiscordIncomingWebhook icon
Pause icon
Tag icon
Push icon
Webhook icon

Digest-Pinned Container Promotion with Approval

Build a Docker image once, pause for human approval, then retag the exact image ID to production and push it with Kestra. No rebuild can slip in.

Categories
Infrastructure

Promote the exact Docker image you tested, never a fresh rebuild. This blueprint builds a candidate image once, captures its immutable image ID, pauses for a human to approve, then retags that same ID to your production reference and pushes it to the registry. Because every downstream step works from the captured image ID instead of a mutable tag, a different or newer build can never slip into production. It closes the classic gap where staging and production tags drift apart and you ship bits nobody reviewed, giving you a safe, auditable Docker promotion gate with approval, notifications, and a webhook entry point.

How it works

  1. A release system triggers the flow through io.kestra.plugin.core.trigger.Webhook (on_promotion_request), guarded by a secret key.
  2. io.kestra.plugin.docker.Build (build) builds the candidate image from the inline dockerfile, tags it with staging_tag, and exposes its immutable imageId as an output. push stays false so nothing ships yet.
  3. io.kestra.plugin.discord.DiscordIncomingWebhook (notify_approval) posts a message announcing that build {{ outputs.build.imageId }} is paused before promotion.
  4. io.kestra.plugin.core.flow.Pause (approve_promotion) halts the execution for up to approval_timeout (default PT4H) until a human resumes it.
  5. io.kestra.plugin.docker.Tag (tag_production) retags sourceImage: {{ outputs.build.imageId }} to targetImage: {{ inputs.production_tag }}.
  6. io.kestra.plugin.docker.Push (push_production) pushes the production tag to ghcr.io using registry credentials.

What you get

  • A promotion that is pinned to the reviewed image ID, not a movable tag.
  • A built-in human approval gate with a configurable timeout.
  • A Discord notification so the right person knows an approval is waiting.
  • A webhook entry point so your CI or release tooling can kick off promotion.
  • Full execution history of who approved which image and when.

Who it's for

  • Platform and DevOps engineers running container release pipelines.
  • SRE teams that need an auditable, gated path to production.
  • Release managers who want a human checkpoint before shipping.

Why orchestrate this with Kestra

A container registry and a Dockerfile have no concept of "the image I approved." Kestra adds the missing control plane: the Webhook trigger turns an external release event into a run, Pause provides a real human approval step with a timeout, retries can be attached to flaky pushes, and every execution captures lineage from build to push. The whole pipeline is declarative YAML you can version and review. Docker's own tooling can build and push, but it cannot pause for approval, notify a team, or guarantee that the pushed image is byte-for-byte the one that was reviewed. That promotion gate is the gap Kestra fills.

Prerequisites

  • A worker with Docker daemon access for the build, tag, and push tasks.
  • A registry (the sample uses ghcr.io) you can push to.

Secrets

  • REGISTRY_USERNAME: username for the container registry push.
  • REGISTRY_PASSWORD: password or token for the registry push.
  • DOCKER_PROMOTE_WEBHOOK_KEY: key guarding the webhook trigger.
  • DISCORD_WEBHOOK_URL: Discord incoming webhook URL for the approval notification.

Quick start

  1. Add the secrets above to your Kestra namespace.
  2. Replace the sample dockerfile with your real build, or adapt build to pull a prebuilt image.
  3. Set staging_tag and production_tag to your registry references.
  4. Trigger the flow (or run it manually), then resume the approve_promotion Pause to promote.

How to extend

  • Swap the build task for a pull of a prebuilt digest if your CI builds images elsewhere.
  • Replace Discord with Slack or email for the approval notification.
  • Add a smoke-test task between Build and Pause and let its result inform the approver.
  • Push the same image ID to multiple registries or environments after approval.
  • Add retries to push_production to absorb transient registry errors.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.