# Lint phase. The linter is invoked directly rather than through `make # lint` or `script/lint`, which are themselves a docker build and would # recurse into a daemon that does not exist in a build step. # golangci/golangci-lint:v2.12.2-alpine, 2026-06-28 FROM golangci/golangci-lint:v2.12.2-alpine@sha256:91b27804074a0bacea298707f016911e60cf0cdbc6c7bf5ccacb5f0606d18d60 AS lint WORKDIR /src # Copy go mod files first for better layer caching COPY go.mod go.sum ./ RUN go mod download # Copy source code COPY . . RUN golangci-lint run ./... # Test phase, invoking `go test` directly for the same reason. -race # needs cgo and so a C compiler, which the Debian Go image ships and the # alpine one does not. The tool shells out to sqlite3, zstdmt and # zstdcat, so tests that run it need them installed. # golang:1.26.4-trixie, 2026-10-05 FROM golang:1.26.4-trixie@sha256:68b7145ec43d1820b9a56704554b53d1520aa2a15cb5233e374188a31b2a1bce AS test RUN apt-get update \ && apt-get install -y --no-install-recommends sqlite3 zstd \ && rm -rf /var/lib/apt/lists/* WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go test -timeout 90s -race -cover ./... || \ { echo "--- Rerunning with -v for details ---"; \ go test -timeout 90s -race -v ./...; exit 1; } # Build stage. Nothing is wanted from either phase above; the copies # are what make BuildKit build them first, so this stage cannot run # unless lint and test passed. A plain `docker build .` builds only the # last stage and what it depends on, so the runtime stage stays last. # golang:1.26.4-alpine, 2026-06-28 FROM golang:1.26.4-alpine@sha256:3ad57304ad93bbec8548a0437ad9e06a455660655d9af011d58b993f6f615648 AS builder COPY --from=lint /src/go.sum /dev/null COPY --from=test /src/go.sum /dev/null ARG VERSION=dev WORKDIR /src # Copy go mod files first for better layer caching COPY go.mod go.sum ./ RUN go mod download # Copy source code COPY . . # Build (pure Go, no CGO required since we use modernc.org/sqlite) RUN CGO_ENABLED=0 go build -o /bsdaily ./cmd/bsdaily # Runtime stage # alpine:3.21, 2026-06-28 FROM alpine:3.21@sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d # bsdaily shells out to sqlite3, zstdmt, zstdcat at runtime RUN apk add --no-cache ca-certificates sqlite zstd # Copy binary from builder COPY --from=builder /bsdaily /usr/local/bin/bsdaily ENTRYPOINT ["/usr/local/bin/bsdaily"]