From f3e1d161d0b777bcec71c9714b5c4e5eb7ea782cbbaec622b091da30b9381303 Mon Sep 17 00:00:00 2001 From: Tyler J King Date: Wed, 22 Apr 2026 12:06:55 -0400 Subject: [PATCH] packaging: production Dockerfile for spire-plugins image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two-stage build. Builder stage: golang:1.23.6-bookworm (pinned to match the go directive in go.mod exactly), CGO_ENABLED=0, -trimpath and -s -w linker flags for reproducible, size-minimized static binaries. Compiles all four plugin binaries into /plugins/. Runtime stage: debian:bookworm-slim with the /plugins/ directory copied in and made world-readable. The image is inert — SPIRE server and agent Deployments consume it via an initContainer that runs `cp -r /plugins/ /opt/spire/plugins/` into a shared emptyDir volume, so no ENTRYPOINT is needed. Path: git.guildhouse.dev/tking/spire-plugins:v0.1.0. Not replacing Containerfile.dev, which remains the local-dev variant. Signed-off-by: Tyler J King --- Dockerfile | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4ee887c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# Guildhouse SPIRE Plugins — production image. +# +# This image is a passive binary container: it is not executed directly. +# SPIRE server/agent Deployments mount an emptyDir volume and run an +# initContainer from this image that copies /plugins/ into the shared +# volume. The runtime layer therefore only needs the plugin binaries +# themselves plus a minimal `cp` — distroless static-nonroot ships a +# BusyBox-less runtime, so we use the bookworm slim minimal base here +# which includes coreutils. +# +# Plugin binary paths are /plugins/. SPIRE's HCL plugin_cmd +# directive expects these exact paths. + +FROM golang:1.23.6-bookworm AS builder + +WORKDIR /src + +# Dependency cache layer — go.mod/go.sum copied first so we only redo +# `go mod download` when module graph changes, not on every source edit. +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +# Build each plugin binary into /plugins/. CGO disabled so the binaries +# are statically linked and runnable from any base image. +ENV CGO_ENABLED=0 +ENV GOOS=linux +ENV GOARCH=amd64 +RUN mkdir -p /plugins && \ + go build -trimpath -ldflags="-s -w" -o /plugins/oidc-attestor ./cmd/oidc-attestor && \ + go build -trimpath -ldflags="-s -w" -o /plugins/ssh-credential-composer ./cmd/ssh-credential-composer && \ + go build -trimpath -ldflags="-s -w" -o /plugins/governance-notifier ./cmd/governance-notifier && \ + go build -trimpath -ldflags="-s -w" -o /plugins/substrate-keymanager ./cmd/substrate-keymanager + +FROM debian:bookworm-slim AS runtime + +# No shell commands needed at image boot — this image is inert. The +# initContainer that uses it supplies its own `cp -r /plugins/ /opt/spire/plugins/` +# command. We keep the binaries readable by any UID so SPIRE's +# non-root user can read them out of the shared volume. +COPY --from=builder /plugins/ /plugins/ +RUN chmod -R a+rx /plugins + +LABEL org.opencontainers.image.source="https://git.guildhouse.dev/tking/guildhouse-spire-plugins" \ + org.opencontainers.image.description="Guildhouse SPIRE plugins: oidc-attestor, ssh-credential-composer, governance-notifier, substrate-keymanager" \ + org.opencontainers.image.licenses="Apache-2.0"