snapshot create compacted the metadata database by running a sqlite3 command-line binary, after every blob had already been uploaded. On a host without that binary, which includes anyone who installed with go install, the backup failed at the last step, and two tests failed the same way. VACUUM now runs through the Go sqlite driver the program already uses, and its error is returned to the caller. The runtime Docker image no longer installs the sqlite package, since nothing in the binary calls it. model: claude-opus-4-8 (implementation, review); claude-fable-5-1 (merge)
87 lines
3.7 KiB
Docker
87 lines
3.7 KiB
Docker
# This file has no lint stage, deliberately.
|
|
#
|
|
# Linting lives in Dockerfile.lint, built by script/lint, and
|
|
# script/cibuild builds both. A lint stage here would have to either
|
|
# shell out to `make lint` -- which is now `docker build`, so
|
|
# docker-in-docker inside a BuildKit step with no daemon -- or call
|
|
# golangci-lint directly, which would mean a second, independently
|
|
# bumpable digest pin for the linter alongside the one in
|
|
# Dockerfile.lint. Two pins for one tool is the drift that
|
|
# https://git.eeqj.de/sneak/vaultik/issues/78 was filed over. See
|
|
# https://git.eeqj.de/sneak/vaultik/issues/113 for the ruling.
|
|
#
|
|
# Consequence, stated rather than left to be discovered: script/docker
|
|
# builds this file only and therefore does not lint. `make fmt-check`
|
|
# and `make test` still run here, so what a green build of this file
|
|
# means is "formatted, tested, and it compiles" -- the lint verdict
|
|
# comes from script/lint or script/cibuild.
|
|
|
|
# Build stage
|
|
# golang:1.26.1-alpine, 2026-03-17
|
|
FROM golang:1.26.1-alpine@sha256:2389ebfa5b7f43eeafbd6be0c3700cc46690ef842ad962f6c5bd6be49ed82039 AS builder
|
|
|
|
ARG VERSION=dev
|
|
|
|
# Build tooling: make, plus a C toolchain because `go test -race` needs cgo.
|
|
# The sqlite driver is pure Go (modernc.org/sqlite), so no sqlite library or
|
|
# CLI is required.
|
|
RUN apk add --no-cache make build-base
|
|
|
|
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 the format check and the tests.
|
|
#
|
|
# CHECK_EPOCH must stay immediately above these RUNs. These layers are
|
|
# keyed on its value, so they are cache-eligible only for a value
|
|
# already built against this same tree. script/cibuild and script/docker
|
|
# each pass a fresh value on every invocation, which is what makes their
|
|
# green mean the checks really executed.
|
|
#
|
|
# The value is expanded into each check command rather than left to a
|
|
# bare declaration, so the cache miss does not depend on BuildKit's
|
|
# unreferenced-ARG handling staying as it is. It also puts the epoch in
|
|
# the build log, where a reader can see the layer was keyed fresh.
|
|
#
|
|
# The guard is what makes a build that omits --build-arg fail instead of
|
|
# lie. An unset ARG is an empty string, and an empty string is a
|
|
# perfectly stable cache key: without the guard the first such build
|
|
# runs the checks and every one after it on an unchanged tree replays
|
|
# these layers from cache, executes nothing, and still exits 0. Failed
|
|
# steps are never cached, so the guard fails on EVERY invocation rather
|
|
# than once -- a bare `docker build .` is a loud error, not a quiet
|
|
# green. Do not give CHECK_EPOCH a default value; a default would
|
|
# satisfy the guard with a constant and restore the hole.
|
|
#
|
|
# Everything above this line (apk, go.mod, `go mod download`) is
|
|
# deliberately outside the busted range and keeps caching.
|
|
ARG CHECK_EPOCH
|
|
RUN [ -n "$CHECK_EPOCH" ] || exit 1
|
|
RUN echo "check epoch: ${CHECK_EPOCH}" && make fmt-check
|
|
RUN echo "check epoch: ${CHECK_EPOCH}" && make test
|
|
|
|
# Build (pure Go, no CGO required since we use modernc.org/sqlite)
|
|
RUN CGO_ENABLED=0 go build -ldflags "-X 'sneak.berlin/go/vaultik/internal/globals.Version=${VERSION}' -X 'sneak.berlin/go/vaultik/internal/globals.Commit=$(git rev-parse HEAD 2>/dev/null || echo unknown)' -X 'sneak.berlin/go/vaultik/internal/globals.CommitDate=$(git show -s --format=%cs HEAD 2>/dev/null || echo unknown)'" -o /vaultik ./cmd/vaultik
|
|
|
|
# Runtime stage
|
|
# alpine:3.21, 2026-02-25
|
|
FROM alpine:3.21@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
|
|
|
RUN apk add --no-cache ca-certificates
|
|
|
|
# Copy binary from builder
|
|
COPY --from=builder /vaultik /usr/local/bin/vaultik
|
|
|
|
# Create non-root user
|
|
RUN adduser -D -H -s /sbin/nologin vaultik
|
|
|
|
USER vaultik
|
|
|
|
ENTRYPOINT ["/usr/local/bin/vaultik"]
|