# Hugo static-site build image. The build runs `make test` -- a clean # `hugo --minify` production build -- so the image build fails on any # template, content or config error. # # It deliberately does NOT run `make check`. `make check` runs # script/lint, and script/lint is a `docker build` of Dockerfile.lint, # so `RUN make check` here would be docker-in-docker inside a bare # alpine with no docker client and no daemon socket. The checks are # therefore split by where they run: the production build here, lint and # the prettier format check in Dockerfile.lint. Do not reintroduce a # `make check` (or a `make lint` / `make fmt-check`) line in this file. # # CI coverage is unaffected: script/cibuild builds this image and then # calls script/lint and script/fmt-check, so every check in `make check` # still runs on every push -- see script/cibuild. # # Build this only via script/cibuild or script/docker: both pass the # CHECK_EPOCH build argument that this file requires, and a bare # `docker build .` fails by design. See the guard below for why. # alpine 3.21, 2026-02-28 FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709 WORKDIR /src # Install build dependencies first so the layer caches until the # scripts change (script/bootstrap installs git, make, go, hugo, # node/npm). Hugo is not an apk package here: script/bootstrap builds # the exact pinned version with `go install`, hash-verified against # sum.golang.org, so the published artifact does not depend on whatever # hugo this base image's repos happen to serve. COPY script/ script/ RUN script/bootstrap COPY . . # CHECK_EPOCH is a per-invocation nonce supplied by script/cibuild and # script/docker. Without it an unchanged tree serves this layer from # cache and the build reports a green it never ran. ARG is stage-scoped, # so it must be redeclared in every stage that runs checks - this image # has one stage, so one declaration. Declared with no default: a default # would be a constant, and a constant is a stable cache key. The guard # makes a bare `docker build .` fail loudly instead of silently reusing # the empty (and therefore stable) cache key. Expand the value into the # command so the cache miss does not depend on BuildKit's handling of an # unreferenced ARG. Both the guard and the check RUN reference the value, # so both are value-keyed: there are two independent invalidation points # here, not one. Keep both. # # Everything above this point still caches, so the script/bootstrap # layer - which compiles Hugo from source - is not rebuilt. ARG CHECK_EPOCH RUN [ -n "$CHECK_EPOCH" ] || exit 1 # Run the production build - build fails if the site does not build. RUN echo "check epoch: ${CHECK_EPOCH}" && make test