Hi! I'm your Kestra AI assistant. Ask me anything about workflows.
EXAMPLE QUESTIONS
How to sync my flows with Git?
How to add secrets?
What is a task runner?
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.
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.
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.
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.
Shell task with the cosign CLI, digest from <code>outputs.build.imageId</code>
Possible via shell, no native pattern
GitHub-provided cosign action
Possible 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 passing
Action-dependent, output passing
Variable 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 pull
Container jobs, registry pull
Container images, registry pull
Short-lived cloud registry tokens
Native ECR, GCP, Azure auth tasks
Custom shell with aws/gcloud CLI
OIDC + glue scripts
OIDC + glue scripts
Event triggers beyond Git push
Webhook, schedule, S3, Kafka, file events, all native
Webhook plugin, polling
Webhook events on the repo
Webhook + pipeline schedule
Per-step retries on transient registry errors
Configurable per task
Pipeline-coded retries
Action-dependent
<code>retry:</code> keyword in job
Per-execution audit history
Execution view + per-task state and digest
Build history
Run history in Actions UI
Pipeline history
Orchestrate beyond CI (data, infra, business workflows)
1300+ plugins
Build-focused
Build-focused
Build-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.
The flow captures imageId (the sha256 digest) from the docker.Build output, then runs cosign sign --yes registry/repo@ via a scripts.shell.Commands task. Two modes are supported: key-based (Cosign private key stored in the Kestra secrets backend) and keyless via Sigstore OIDC (set COSIGN_EXPERIMENTAL=1, no key management needed). Signing the digest, not the tag, binds the signature to the immutable artifact, so retagging or repushing under a different tag doesn't break verification.
Tags are mutable. The same latest tag can point to different images at different times, which means the artifact that passed your tests is not guaranteed to be the artifact running in prod. A sha256 digest is the cryptographic identity of the image bytes. Capture outputs.build.imageId at build time, push it under a staging tag, run your tests against repo@sha256:..., then retag the same digest for prod. The promotion never rebuilds, never repulls a base image, never lets in drift.
Yes. docker.Compose brings up a stack with the dependencies your tests need (Postgres, Redis, queue, the app). Use a unique compose project name per execution (-p pr-{{ trigger.body.pr_number }}) so parallel runs don't collide. Always put a second docker compose down -v task in the errors branch, otherwise a failed test leaves containers and volumes on the runner. --wait on compose up plus Compose v2 healthchecks gives you 'service is ready' semantics.
Yes. Capture outputs.build.imageId from docker.Build, then set it on the next task: containerImage: "{{ outputs.build.imageId }}" with the Docker task runner and pullPolicy: NEVER. The task runs in the local image you just built, without a registry round-trip. This is the pattern data scientists use to ship a custom Python runtime and the workload that needs it in one execution.
Docker is a CLI. It builds and pushes images when you run the command, but it has no scheduler, no event triggers, no pause-and-resume between staging and prod, no native chaining with cloud auth, and no shared history for the steps that run before or after. Kestra adds all of those. Every docker build becomes a workflow step: triggered on Git push or schedule, gated by a reviewer, scanned and signed before push, retried on transient registry errors, and auditable across the full pipeline including the deploy step. The same flows can pair Docker with Ansible for host configuration, with Terraform for the underlying infrastructure, and with the broader infrastructure automation patterns Kestra supports.
It can, but it doesn't have to. Many teams start by adding Kestra above an existing CI: GitHub Actions builds the image and posts the digest, Kestra picks it up via webhook, runs Trivy + Cosign, pauses for approval, and triggers the Kubernetes rollout against the signed digest. When the team is ready, the build itself can move into Kestra with docker.Build.
Each cloud has a Kestra task for short-lived credentials. aws.ecr.GetAuthToken returns a 12-hour ECR token. gcp.auth.OauthAccessToken returns a one-hour OAuth token for Artifact Registry (use accessToken.tokenValue in the password field). azure.auth.OauthAccessToken returns an ACR token. docker.Build and docker.Push consume them directly via the credentials property. No long-lived registry passwords in CI variables.
docker.Build accepts a platforms array, passed straight to buildx. Set platforms: [linux/amd64, linux/arm64] and the daemon builds both, tags them under the same manifest list, and pushes the manifest in one step. No separate workflow per architecture.
On whichever worker the task is scheduled on. For local builds, mount the host's Docker socket: volumes: [/var/run/docker.sock:/var/run/docker.sock] on the Docker task runner. On Kubernetes, use a DinD sidecar or a remote daemon endpoint via the host: property. Per-worker isolation means the prod-push worker doesn't see staging credentials.
No. The io.kestra.plugin.docker plugin ships in the open-source edition. Kestra Enterprise adds Apps, namespace-scoped RBAC, audit logs, worker isolation, and SSO, which teams running multi-tenant build platforms typically want on top.
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.