Author SHA1 Message Date
sneak 99c959d0ed Keep the module cache out of the build stage's chown (closes #43)
check / check (push) Waiting to run
The build stage handed /src and the whole Go module cache to the
unprivileged user with chown -R, in a layer that re-ran on every source
change. On this host that step took minutes and lately stalled
script/cibuild outright.

The module cache now sits at /go/pkg/mod and stays root's: bootstrap
fills it as root and builder only reads it. The sources are copied with
--chown. A small chown, cached with bootstrap, hands builder the /src
directory itself, which git and make build need, and the telemetry
files root's go commands left in its home. Tests and the build still
run as builder.

Model: opus-5-5
2026-10-04 02:22:59 +00:00
2 changed files with 25 additions and 8 deletions
+21 -8
View File
@@ -51,14 +51,22 @@ RUN echo "gate lint, epoch ${CHECK_EPOCH}" && \
FROM golang@sha256:56961d79ea8129efddcc0b8643fd8a5416b4e6228cfd477e3fd61deb2672c587 AS builder
# We never build or run as root. Create an unprivileged user and point
# HOME and the Go caches at its home so go build and go test can write
# their caches when we drop to it below. $GOPATH/bin is deliberately not
# on PATH: script/bootstrap no longer `go install`s anything (the linter
# runs from a pinned image, never from a host install), so nothing lands
# HOME and the build cache at its home so go build and go test can write
# it when we drop to it below. $GOPATH/bin is deliberately not on PATH:
# script/bootstrap no longer `go install`s anything (the linter runs
# from a pinned image, never from a host install), so nothing lands
# there and adding it would only widen what this image resolves.
#
# The module cache is kept outside that home, at the base image's
# default /go/pkg/mod, and belongs to root: script/bootstrap fills it as
# root, and builder only reads it, which is all Go does with a cache
# that already holds every module. Do not move it into the home and
# hand it over with `chown -R`: that walks every file in it and can
# stall the build for half an hour on a loaded host.
RUN adduser -D -u 1000 builder
ENV HOME=/home/builder
ENV GOPATH=/home/builder/go
ENV GOMODCACHE=/go/pkg/mod
ENV GOCACHE=/home/builder/.cache/go-build
WORKDIR /src
@@ -83,11 +91,16 @@ COPY script/ script/
COPY go.mod go.sum ./
RUN script/bootstrap
COPY . .
# /src itself must be builder's: make build writes the binary into it,
# and git refuses a repository whose top directory belongs to another
# user. The go commands bootstrap ran as root also left Go's telemetry
# files in builder's home. Both are a few small files, and this layer
# stays cached with bootstrap.
RUN chown builder:builder /src && chown -R builder:builder /home/builder
# Hand the sources and caches to the unprivileged user, then drop root
# before running any checks or builds.
RUN chown -R builder:builder /src /home/builder
# The sources are handed to builder as they are copied, so no layer has
# to walk them. Then drop root before running any checks or builds.
COPY --chown=builder:builder . .
USER builder
# Fail the build unless the branch is green. Runs as non-root so the
+4
View File
@@ -29,6 +29,10 @@
# Completed Steps
- the `Dockerfile` build stage leaves the Go module cache root's and copies
the sources with `--chown`, so no `chown -R` walks them (2026-10-04,
https://git.eeqj.de/sneak/sfdupes/issues/43)
- warn about and skip symlink, socket, FIFO, device and `.zfs`
operands, keeping the records beneath them (2026-10-03,
https://git.eeqj.de/sneak/sfdupes/issues/9)