Sign Docker digests once. Promote them everywhere.

Build, scan with Trivy, sign with Cosign, and push in one flow. Promote the same sha256 digest from staging to prod without rebuilding, bring up Compose stacks for integration tests with guaranteed teardown, and reuse images as task runtimes.

Around every docker build, every digest, every stack.

What Kestra wraps around your Docker pipelines: how images get signed, how a single sha256 digest travels from staging to prod, how Compose stacks come up for tests and tear down on every exit path, and where the audit lives.

Build, Trivy scan, Cosign sign, in one flow

docker.Build produces the image and emits the imageId (sha256 digest). trivy.cli.TrivyCLI fails the flow on HIGH or CRITICAL CVEs. A shell task runs cosign sign --key cosign.key against the digest, not the tag. Admission controllers downstream can verify the signature is on the same artifact you tested.

Promote the same digest, never rebuild between environments

Capture the imageId from the build step, push it to the staging registry, run smoke tests, then push the same digest to the prod registry under a new tag. The artifact you signed and scanned is the artifact you ship. Tags are mutable, sha256 is not.

Compose stacks for ephemeral integration tests

docker.Compose brings up a full stack (app, Postgres, Redis, queue) for the duration of one flow. Tests run against the live stack. An errors branch fires docker compose down -v on every exit path, so containers and volumes never leak across CI runs.

Build a custom task-runner image and use it in the same flow

docker.Build produces a Python or R image with your data dependencies pre-installed. The next task, scripts.python.Commands, references that imageId as its containerImage with pullPolicy: NEVER. One execution covers build, test, and the workload that uses the image.

Short-lived ECR, Artifact Registry, ACR tokens

aws.ecr.GetAuthToken, gcp.auth.OauthAccessToken, and azure.auth.OauthAccessToken fetch fresh credentials at the start of the run. docker.Build and docker.Push consume them through the credentials property. No registry passwords sit in CI variables.

Approval gate between staging and prod registry push

Build once, push the digest to staging. The Pause task surfaces the scan summary, the signature, and the digest in the UI. A named reviewer approves, then the same digest gets a prod tag and a second docker.Push ships it. Reviewer identity and resume timestamp land in the execution history.

How platform teams use Docker and Kestra

Patterns DevOps and platform engineers run in production today. Each one shows the flow end to end, with the real plugin classes in play.

Supply chain

Build, Trivy scan, Cosign sign, push the signed digest

docker.Build produces the image and emits the digest. trivy.cli.TrivyCLI scans and fails on HIGH/CRITICAL. A shell step runs cosign sign against the digest using a key from the Kestra secrets backend (keyless via Sigstore works too). The signed digest pushes to the registry along with its .sig reference. Admission controllers verify on deploy.

Sign the digest, not the tag

Cosign binds the signature to the immutable sha256, so retagging doesn't break verification.

Trivy gate before sign

Scan exits non-zero on HIGH/CRITICAL. The flow halts, the sign step never runs on a vulnerable image.

SBOM stored per execution

Trivy outputs the SBOM as a task artifact, downloadable from the execution UI alongside the signature.

Keyless option via Sigstore

Use OIDC-based keyless signing (COSIGN_EXPERIMENTAL=1) when you don't want to manage Cosign keys.

Git tag webhook
release
docker build
emits sha256
trivy scan
fail on HIGH
cosign sign
digest, not tag
docker push
image + .sig
notify
Slack with digest
Promotion

Digest-pinned promotion from staging to prod

Build the image once, capture the imageId (sha256). Push to the staging registry under the version tag. Run smoke tests against the staging digest. The Pause task surfaces the digest. On approval, docker.Tag retags the same digest for prod and docker.Push promotes it. The artifact tested in staging is bit-for-bit the artifact running in prod.

Never rebuild between envs

The same sha256 moves from dev to staging to prod, so what was scanned is what ships.

Pin smoke tests to the digest

Pull repo@sha256:..., not repo:latest, so the test runs against the artifact you'll promote.

Reviewer logged on approval

Pause records the resumer and resume timestamp, attached to the execution.

Rollback is a retag

Re-promote the previous digest under the prod tag if the new version fails post-deploy.

tag webhook
vX.Y.Z
docker build
capture digest
push staging
vX.Y.Z-staging
smoke test
pull by digest
approve promotion
Pause + reviewer
retag for prod
same digest
push prod
vX.Y.Z
Ephemeral stack

Compose stack for integration tests with guaranteed teardown

On a PR webhook, docker.Compose brings up the full stack: app container, Postgres, Redis, message queue. A health-check loop waits until services accept connections. The test runner executes against the live stack. The errors branch fires docker compose down -v so containers and volumes never survive a failed run.

Teardown on every exit path

An errors branch runs compose down -v on test failures, so volumes never leak.

Health check before test

Probe app, db, and queue with core.http.Request retry until ready. No flaky 'connection refused' on first run.

Network-isolated by default

Services reach each other on the internal Compose network. No host port conflicts across parallel runs.

PR-scoped execution history

Every PR run has its own execution, its own compose project, its own log.

PR webhook
integration tests
compose up
full stack
wait for ready
health probe loop
run tests
pytest / go test
post results
PR comment
compose down
errors branch too
Task runner

Build a custom task-runner image and use it in the same flow

docker.Build produces a Python image with pandas, polars, and your internal libraries pre-installed. The next task, scripts.python.Commands, references the freshly built imageId as its containerImage with pullPolicy: NEVER. Data scientists ship a custom runtime and the workload that needs it in one execution.

Same flow, build + use

No registry push needed for the build/use loop, pullPolicy: NEVER references the local image directly.

imageId is the contract

outputs.build.imageId is the sha256, so the runtime is pinned to the exact build.

Per-namespace task-runner images

Different teams build and use their own runtime image without polluting a shared base.

Git push
data-tools repo
docker build
custom python image
python workload
containerImage = imageId
output to S3
results
Kestra's declarative model and Terraform integration gave us exactly what we needed to build customer-specific pipelines, automate deployment, and monitor everything reliably.
Lirav Duvshani, CEO @DataFlooder · Sopht

Blueprints for Docker orchestration.

One blueprint per use case above. Copy the YAML, point it at your registry, ship it.

Build, scan, sign, push
Digest-pinned promotion
Compose ephemeral test environment

Supply-chain: Build, Trivy scan, Cosign sign, push the signed digest

Builds the image, runs Trivy, signs the digest with Cosign keyless via Sigstore OIDC (or a stored key), then pushes the image and the .sig reference. The exact digest is logged for the downstream deploy step to verify.

Explore Blueprints

Promote the same sha256 digest from staging to prod

Builds once, pushes to staging, runs smoke tests against the staging digest, pauses for a named reviewer, then retags the exact same digest for prod and pushes. The artifact that was tested is the artifact that ships.

Explore Blueprints

Bring up a Compose stack for integration tests, tear down on every exit

docker.Compose starts the app + Postgres + Redis stack from an inline Compose file. Tests run against the live stack. The errors branch always runs compose down -v so volumes and containers never leak, even on test failure or timeout.

Explore Blueprints

Kestra vs Docker pipeline alternatives

Capability
Jenkins
GitHub Actions
GitLab CI
Sign the digest with Cosign as a flow step
Shell task with the cosign CLI, digest from <code>outputs.build.imageId</code>
Possible via shell, no native patternGitHub-provided cosign actionPossible via shell, no native pattern
Digest-pinned promotion across environments
<code>imageId</code> flows forward, <code>docker.Tag</code> retags by digest
Pipeline-coded, parameter passingAction-dependent, output passingVariable passing across jobs
Compose stack lifecycle with guaranteed teardown
Native <code>docker.Compose</code> task plus <code>errors</code> branch
post-build cleanup step<code>if: always()</code> teardown step<code>after_script</code> teardown
Reuse the built image as the next task's runtime
<code>containerImage</code> on the next task references the imageId
Custom container agents, registry pullContainer jobs, registry pullContainer images, registry pull
Short-lived cloud registry tokens
Native ECR, GCP, Azure auth tasks
Custom shell with aws/gcloud CLIOIDC + glue scriptsOIDC + glue scripts
Event triggers beyond Git push
Webhook, schedule, S3, Kafka, file events, all native
Webhook plugin, pollingWebhook events on the repoWebhook + pipeline schedule
Per-step retries on transient registry errors
Configurable per task
Pipeline-coded retriesAction-dependent<code>retry:</code> keyword in job
Per-execution audit history
Execution view + per-task state and digest
Build historyRun history in Actions UIPipeline history
Orchestrate beyond CI (data, infra, business workflows)
1300+ plugins
Build-focusedBuild-focusedBuild-focused

Docker & Kestra: common questions

Find answers to your questions right here, and don't hesitate to Contact Us if you couldn't find what you're looking for.

See How

Ready to ship signed digests and Compose stacks?

Build, scan with Trivy, sign with Cosign, promote the same sha256 from staging to prod without rebuilding, and bring up Compose stacks for tests with guaranteed teardown. Open source, self-hosted, event-driven.