Docker¶
Real docker buildx invocations against a real remote BuildKit endpoint
— nothing here is mocked. A build genuinely runs on that endpoint and a
push genuinely lands in a real registry. See BDD
conventions for the "define, then act"
pattern these steps build on, and Resources for the
Directory/File construction this domain reuses (a build context is
just a Directory, and registry credentials are just a File).
Docker Buildx Builder¶
Given Docker Buildx Builder "<RemoteBuilder>" named "my-builder" at "tcp://buildkit.example.com:1234"
Given Docker Buildx Builder known as "<RemoteBuilder>":
| PROPERTY | VALUE |
| name | my-builder |
| endpoint | tcp://buildkit.example.com:1234 |
Registers a remote BuildKit endpoint. No live check at construction —
same reasoning as RestEndpoint: there's no cheap read-only
probe for "is a remote buildkitd reachable" that isn't itself the real
action (create) this object exists to perform. endpoint may be
written as a <Resource> alias instead of a literal, same as any other
Helm/Docker field.
Negative-path tests (unknown field, missing name/endpoint, an
unregistered <Resource> alias) follow the same shape as every other
alias type — see features/docker/docker-buildx-builder-validation-{short,full}.feature.
Create / remove a Docker Buildx Builder¶
When I create Docker Buildx Builder known as "<Resource>"
When I create Docker Buildx Builder known as "<Resource>" with:
When I create Docker Buildx Builder "<Resource>" with {flags}
When I remove Docker Buildx Builder known as "<Resource>"
When I remove Docker Buildx Builder known as "<Resource>" with:
When I remove Docker Buildx Builder "<Resource>" with {flags}
create runs docker buildx create --name <name> --driver remote
<endpoint> ...args; remove runs docker buildx rm <name> — the
cleanup half, mirroring Helm's install/uninstall pair. Every scenario
that creates a builder removes it again, reachable from the .feature
file itself (Thomas's usual per-scenario cleanup discipline) — this
domain doesn't do idempotent reuse across scenarios the way a
production caller might; that kind of reuse is a .feature-file-level
Background concern, not something the domain itself special-cases.
Given Docker Buildx Builder "<RemoteBuilder>" named "my-builder" at "tcp://buildkit.example.com:1234"
When I create Docker Buildx Builder known as "<RemoteBuilder>"
Then the command exited with 0
When I remove Docker Buildx Builder known as "<RemoteBuilder>"
Then the command exited with 0
Given Docker Buildx Builder known as "<RemoteBuilder>":
| PROPERTY | VALUE |
| name | my-builder |
| endpoint | tcp://buildkit.example.com:1234 |
When I create Docker Buildx Builder known as "<RemoteBuilder>"
Then the command exited with 0
When I remove Docker Buildx Builder known as "<RemoteBuilder>"
Then the command exited with 0
Build and push an image¶
When I build and push "<image-ref>" from "<build-context>" using Docker Buildx Builder known as "<Resource>" with:
When I build and push "<image-ref>" from "<build-context>" using Docker Buildx Builder known as "<Resource>" with {flags}
Runs docker buildx build --builder <name> -t <image-ref> --push
<build-context> ...args. <image-ref> is a literal image reference.
<build-context> may be a literal path or a <Resource> alias
(Directory, same as any Helm chart source) resolved the same way
every other alias field resolves.
One OPTION|VALUE row has a documented, named-exception meaning (same
category as HelmRelease.chart/RestEndpoint.service): --registry-credentials
<FileAlias> is never passed to docker argv literally. It's
intercepted, resolved to a real docker-config-JSON File, and turned
into a scoped DOCKER_CONFIG directory instead — a real environment
difference no CLI flag can express (a real docker buildx build
credential is read from $DOCKER_CONFIG/config.json, not a flag). The
ambient buildx/ state is copied into the scratch directory first, so
the already-created builder stays visible under the scoped config too.
When I build and push "registry.example.com/app:v1" from "./app" using Docker Buildx Builder known as "<RemoteBuilder>" with --platform linux/amd64
Then the command exited with 0
When I build and push "registry.example.com/app:v1" from "./app" using Docker Buildx Builder known as "<RemoteBuilder>" with:
| OPTION | VALUE |
| --platform | linux/amd64 |
Then the command exited with 0
With scoped registry credentials:
Given File known as "<DockerConfig>":
| PROPERTY | VALUE |
| path | ./fixtures/config.json |
When I build and push "registry.example.com/app:v1" from "./app" using Docker Buildx Builder known as "<RemoteBuilder>" with:
| OPTION | VALUE |
| --registry-credentials | <DockerConfig> |
Assertions¶
Every action above sets lastCommandResult the same way every other
domain does — reuse common.step.ts's exit-code/output/JMESPath
assertions (Then the command exited with {int}, Then the command
result data has:, etc.). No new Then vocabulary exists or is needed
for this domain.
Real fixtures for dogfooding this domain¶
features/docker/docker-buildx-builder-{short,full}.feature deploy a
real, disposable registry (charts/test-registry) and a real,
disposable BuildKit instance (the buildkit-service chart, configured
via fixtures/docker/buildkitd.toml to trust that registry as plain
HTTP) into thomas-helm-test, then build and push a real image
(fixtures/docker/Dockerfile) end to end.
PodSecurity: a real BuildKit pod needs privileged (or
rootless-but-unconfined) execution, which the cluster's default
baseline PodSecurity level blocks. Each scenario labels
thomas-helm-test pod-security.kubernetes.io/enforce=privileged
(I label namespace) right before installing BuildKit,
and removes the label again right after uninstalling it — so a
recreated namespace needs no manual setup, and it only stays privileged
for as long as BuildKit runs (unless a scenario fails mid-way, in which
case the label is left behind until the next successful run). Labeling
a namespace needs cluster-scoped access CI's ServiceAccount doesn't
have, so both features are tagged @requires-broad-rbac and skipped in
CI — see CI.