Keep the module cache out of the build stage's chown (closes #43)
check / check (push) Successful in 1m38s
check / check (push) Successful in 1m38s
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
This commit is contained in:
+21
-8
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user