Check image carries the Go toolchain and module cache; drop them from the final layer #28

Open
opened 2026-08-09 17:29:42 +02:00 by clawbot · 0 comments
Collaborator

Problem

Since #26 the Dockerfile's bootstrap layer compiles Hugo with go install,
and the Go toolchain plus the module cache stay in the image.

Measured growth, main before #26 vs after:

metric before after
docker image inspect 60 MB 683 MB
docker images 84.4 MB 2.25 GB
docker history, bootstrap layer alone 1.56 GB

So 11x to 27x depending which number you read. The 683 MB figure quoted in
PR #27 is the most flattering of the three and should not be the one that
gets repeated.

Why it is not urgent

The image is only ever built to run make checkscript/cibuild is
docker build . and the result is discarded. It is never published, never
pulled, never deployed. The policy budget is on build time, and that is
fine: 2m26s cold against a five-minute limit.

So this is disk and cache pressure on the build host, not a shipped artifact
problem. Filing it because a 27x jump should be a recorded decision rather than
something discovered later by someone wondering where the disk went — this is a
shared host and other repos' builds compete for the same cache.

Fix

Standard approach is a multi-stage build: compile Hugo in a builder stage, copy
only the resulting binary into the final stage, and leave GOPATH/GOCACHE
behind. REPO_POLICIES.md already contemplates multistage builds for Go repos.

Worth checking first whether it is worth doing at all: if the toolchain layer
caches well and the host has the space, the simpler answer is to leave it and
close this as accepted. Measure before changing.

Definition of done

  1. Either the image size is materially reduced and the numbers are reported by
    the same metric before and after, or this is closed as accepted with the
    reasoning written down.
  2. If changed: hugo version in the final image still reports the pinned
    version from script/bootstrap, and the hash-verified install path from #26
    is preserved — the binary must still come from the verified build, not from
    a distro package or an unpinned download.
  3. Cold build time does not regress past the five-minute budget. Report it.
  4. make check passes and script/cibuild succeeds with the check layer
    genuinely executed, not CACHED (#23).
  5. TODO.md updated in the same commit.

Sequencing

  • Interacts with #23. A multi-stage build changes which layers exist, so #23's
    cache-busting fix and this should not land blind of each other. If #23 lands
    first, re-verify its two-consecutive-runs proof after this.
  • Touches script/bootstrap, which runs in deploy.yml's build job, so the
    same rule as #26 applies: if the install path changes, verify on a real
    runner via a temporary branch trigger before merging. If only the
    Dockerfile changes and script/bootstrap is untouched, the deploy path is
    unaffected and that is not needed — state which case applies.

Out of scope

  • Changing the Hugo version or how it is verified (#26 settled that).
  • The proxy.golang.org dependency the deploy path now has.
## Problem Since #26 the `Dockerfile`'s bootstrap layer compiles Hugo with `go install`, and the Go toolchain plus the module cache stay in the image. Measured growth, `main` before #26 vs after: | metric | before | after | | --- | --- | --- | | `docker image inspect` | 60 MB | 683 MB | | `docker images` | 84.4 MB | 2.25 GB | | `docker history`, bootstrap layer alone | — | 1.56 GB | So 11x to 27x depending which number you read. The 683 MB figure quoted in PR #27 is the most flattering of the three and should not be the one that gets repeated. ## Why it is not urgent The image is only ever built to run `make check` — `script/cibuild` is `docker build .` and the result is discarded. It is never published, never pulled, never deployed. The policy budget is on build **time**, and that is fine: 2m26s cold against a five-minute limit. So this is disk and cache pressure on the build host, not a shipped artifact problem. Filing it because a 27x jump should be a recorded decision rather than something discovered later by someone wondering where the disk went — this is a shared host and other repos' builds compete for the same cache. ## Fix Standard approach is a multi-stage build: compile Hugo in a builder stage, copy only the resulting binary into the final stage, and leave `GOPATH`/`GOCACHE` behind. `REPO_POLICIES.md` already contemplates multistage builds for Go repos. Worth checking first whether it is worth doing at all: if the toolchain layer caches well and the host has the space, the simpler answer is to leave it and close this as accepted. Measure before changing. ## Definition of done 1. Either the image size is materially reduced and the numbers are reported by the same metric before and after, or this is closed as accepted with the reasoning written down. 2. If changed: `hugo version` in the final image still reports the pinned version from `script/bootstrap`, and the hash-verified install path from #26 is preserved — the binary must still come from the verified build, not from a distro package or an unpinned download. 3. Cold build time does not regress past the five-minute budget. Report it. 4. `make check` passes and `script/cibuild` succeeds with the check layer genuinely executed, not `CACHED` (#23). 5. `TODO.md` updated in the same commit. ## Sequencing - Interacts with #23. A multi-stage build changes which layers exist, so #23's cache-busting fix and this should not land blind of each other. If #23 lands first, re-verify its two-consecutive-runs proof after this. - Touches `script/bootstrap`, which runs in `deploy.yml`'s `build` job, so the same rule as #26 applies: if the install path changes, verify on a real runner via a temporary branch trigger before merging. If only the `Dockerfile` changes and `script/bootstrap` is untouched, the deploy path is unaffected and that is not needed — state which case applies. ## Out of scope - Changing the Hugo version or how it is verified (#26 settled that). - The `proxy.golang.org` dependency the deploy path now has.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/lora.vegas#28