@flowwright/plugin-docker
Turns one options object into up to three stages: login, build, push.
npm install --save-dev @flowwright/plugin-docker
API
| Export | Kind | Signature |
|---|---|---|
dockerStages | stage builder | (options: DockerImageOptions) => StageDefinition[] |
dockerBuild | stage builder | (options: Omit<DockerImageOptions, "push" | "login">) => StageDefinition |
DockerImageOptions — image is the only required field:
| Option | Default | Meaning |
|---|---|---|
image | required | Repository, e.g. acme/api |
tag | "latest" | Primary tag |
extraTags | — | Additional 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 |
platforms | — | Multi-arch; implies buildx |
cacheFrom, cacheTo | — | Registry cache; implies buildx |
buildx | auto | Force docker buildx build |
push | false | Add a push stage, or --push under buildx |
login | — | true, or { credential, registry } |
digest | — | true writes image.digest; a string names the file |
needs | — | Dependencies for whichever stage heads the chain |
Example
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
| Stage | id | When |
|---|---|---|
| Docker Login | docker-login | login is set |
| Docker Build | docker-build | always |
| Docker Push | docker-push | push 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.