Skip to main content

@flowwright/plugin-docker

Turns one options object into up to three stages: login, build, push.

npm install --save-dev @flowwright/plugin-docker

API

ExportKindSignature
dockerStagesstage builder(options: DockerImageOptions) => StageDefinition[]
dockerBuildstage builder(options: Omit<DockerImageOptions, "push" | "login">) => StageDefinition

DockerImageOptionsimage is the only required field:

OptionDefaultMeaning
imagerequiredRepository, e.g. acme/api
tag"latest"Primary tag
extraTagsAdditional tags on the same build
context"."Build context
dockerfile"Dockerfile"Path to the Dockerfile
buildArgs, labels--build-arg / --label pairs
target--target for a multi-stage Dockerfile
pull--pull
platformsMulti-arch; implies buildx
cacheFrom, cacheToRegistry cache; implies buildx
buildxautoForce docker buildx build
pushfalseAdd a push stage, or --push under buildx
logintrue, or { credential, registry }
digesttrue writes image.digest; a string names the file
needsDependencies for whichever stage heads the chain

Example

pipeline.ts
import { pipeline, stage, sh } from "@flowwright/core";
import { dockerStages } from "@flowwright/plugin-docker";

export default pipeline({
name: "acme-api",
stages: [
stage("Build", {
id: "build",
run: async () => {
await sh(["npm", "run", "build"]);
},
}),
...dockerStages({
image: "acme/api",
tag: "1.0",
extraTags: ["latest"],
needs: ["build"],
login: { registry: "ghcr.io" },
push: true,
}),
],
});

What it composes down to

StageidWhen
Docker Logindocker-loginlogin is set
Docker Builddocker-buildalways
Docker Pushdocker-pushpush and not buildx

For the example above:

docker-login ← build
$ echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin ghcr.io
docker-build ← docker-login
$ docker build -t acme/api:1.0 -t acme/api:latest -f Dockerfile .
docker-push ← docker-build
$ docker push acme/api:1.0
$ docker push acme/api:latest

needs goes to whichever stage heads the chain — login when present, otherwise build — and the rest follow transitively.

Login declares { id: "docker-registry", as: "usernamePassword", usernameEnv: "DOCKER_USERNAME", passwordEnv: "DOCKER_PASSWORD" }, overridable with login.credential.

buildx

platforms, cacheFrom or cacheTo switch to docker buildx build, and push becomes a --push flag instead of a separate stage:

docker-build
$ docker buildx build -t acme/api:latest -f Dockerfile --platform linux/amd64,linux/arm64 --push .

Single-platform and not pushing gets --load, so the image lands in your local daemon.

Gotchas

Multi-platform without push produces nothing you can use. buildx can't --load more than one architecture, so the build runs and the result is discarded. Either push it or build one platform.

dockerBuild() doesn't accept push or login. They exist to produce the other two stages, and under buildx push changes the build argv itself — so accepting and dropping them would hand back an image that can't be published. Passing either throws; use dockerStages().

login.registry is interpolated into a shell command. It's your own value, but keep it a plain hostname.

Container stages need a working Docker daemon. These stages run docker on the host, so they're subject to the same fallback rules as any container work — see Containers.