Build the api outside the image it ships in #61

Merged
PerishFire merged 1 commit from build-outside into main 2026-08-01 10:44:33 +00:00
Owner

deploy/api.Dockerfile ran cargo inside the image build, so it needed the
private registry from in there. That is why ship passed --network=host and
mounted cargo credentials as a build secret — a debt this repository has been
carrying with a note attached saying it gives up build isolation instead of
giving a route.

The route was already on the runner. It carries the Rust toolchain and the
registry credentials that guard's clippy and tests use on every run. So ship
now builds the release binary first, stages it beside the Dockerfile, and the
Dockerfile drops to a runtime stage that copies it.

  • no cargo in the image build
  • no --secret id=cargo
  • no --network=host

A .dockerignore arrives with it: the context is now what the runtime stage
actually reads, rather than target/ and node_modules/ being handed to the
daemon on every build.

Verified by building the image with neither the secret nor the host network and
running it — bootstrap and serve both resolve.

This is the decision recorded as 15 in the task line. The alternative
considered and rejected was putting the api binary into [release] binaries
so the image could copy a release artifact. That field is not an inventory of
what the repository produces; it is the set a generated manager installs onto
a user's PATH, so it would have handed a server binary to everyone installing
the CLI. The repository ships two independent distribution lines and this keeps
them apart.

Guard was run in full on the committed state and is clean, including all six
acts.

`deploy/api.Dockerfile` ran cargo inside the image build, so it needed the private registry from in there. That is why `ship` passed `--network=host` and mounted cargo credentials as a build secret — a debt this repository has been carrying with a note attached saying it gives up build isolation instead of giving a route. The route was already on the runner. It carries the Rust toolchain and the registry credentials that guard's clippy and tests use on every run. So `ship` now builds the release binary first, stages it beside the Dockerfile, and the Dockerfile drops to a runtime stage that copies it. - no cargo in the image build - no `--secret id=cargo` - no `--network=host` A `.dockerignore` arrives with it: the context is now what the runtime stage actually reads, rather than `target/` and `node_modules/` being handed to the daemon on every build. Verified by building the image with neither the secret nor the host network and running it — `bootstrap` and `serve` both resolve. This is the decision recorded as 15 in the task line. The alternative considered and rejected was putting the api binary into `[release] binaries` so the image could copy a release artifact. That field is not an inventory of what the repository produces; it is the set a generated manager installs onto a user's PATH, so it would have handed a server binary to everyone installing the CLI. The repository ships two independent distribution lines and this keeps them apart. Guard was run in full on the committed state and is clean, including all six acts.
Build the api outside the image it ships in
All checks were successful
guard / guard (pull_request) Successful in 3m41s
guard / guard (push) Successful in 3m36s
3791074733
The Dockerfile ran cargo inside the build, so it needed the private registry
from in there, which is why ship passed --network=host and mounted cargo
credentials as a secret. Trading build isolation for a route was never the
answer; the route was already on the runner, which carries the toolchain and
the credentials that guard's clippy and tests already use.

Ship now builds the release binary first and stages it beside the Dockerfile,
which drops to a runtime stage that copies it. No cargo, no secret, no host
network. A .dockerignore keeps the context to what the runtime stage reads
rather than shipping target/ and node_modules/ to the daemon.

Verified by building the image with neither the secret nor --network=host and
running it: both subcommands resolve.
PerishFire deleted branch build-outside 2026-08-01 10:44:33 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
PerishLab/ensign!61
No description provided.