# Multi-stage Containerfile for fjmcp-broker. # # Stage 1: build fjmcp-broker (this repo). # Stage 2: build forgejo-mcp at a pinned version. The broker spawns it as # a subprocess per session, so it must live in the final image. # Stage 3: distroless static-nonroot. CGO_ENABLED=0 in both build stages # keeps the final image free of glibc/musl entanglements and # makes the image entirely static. # # Build labels and /etc/build-info wire BUILD_DATE and GIT_REVISION so # operators can correlate a running container back to a commit. ARG BUILD_DATE="unknown" ARG GIT_REVISION="unknown" ARG FORGEJO_MCP_VERSION="2.18.0" # ---------- Stage 1: broker build ---------- FROM docker.io/library/golang:1.26-alpine AS broker-build WORKDIR /src RUN apk add --no-cache git COPY go.mod go.sum ./ RUN go mod download COPY . . ARG BUILD_DATE ARG GIT_REVISION ENV CGO_ENABLED=0 RUN go build \ -trimpath \ -ldflags "-s -w \ -X kode.naiv.no/olemd/forgejo-mcp-broker/internal/buildinfo.Version=${GIT_REVISION} \ -X kode.naiv.no/olemd/forgejo-mcp-broker/internal/buildinfo.GitRevision=${GIT_REVISION} \ -X kode.naiv.no/olemd/forgejo-mcp-broker/internal/buildinfo.BuildDate=${BUILD_DATE}" \ -o /out/fjmcp-broker \ ./cmd/broker # ---------- Stage 2: forgejo-mcp build ---------- FROM docker.io/library/golang:1.26-alpine AS mcp-build WORKDIR /src RUN apk add --no-cache git ARG FORGEJO_MCP_VERSION RUN git clone --depth=1 --branch v${FORGEJO_MCP_VERSION} \ https://codeberg.org/goern/forgejo-mcp.git . \ && CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o /out/forgejo-mcp . # ---------- Stage 3: runtime ---------- FROM gcr.io/distroless/static-debian12:nonroot ARG BUILD_DATE ARG GIT_REVISION ARG FORGEJO_MCP_VERSION LABEL org.opencontainers.image.title="fjmcp-broker" LABEL org.opencontainers.image.description="OAuth 2.1 broker that fronts forgejo-mcp for MCP clients." LABEL org.opencontainers.image.source="https://kode.naiv.no/olemd/forgejo-mcp-broker" LABEL org.opencontainers.image.created="${BUILD_DATE}" LABEL org.opencontainers.image.revision="${GIT_REVISION}" LABEL org.opencontainers.image.licenses="MIT" LABEL net.naiv.fjmcp.forgejo-mcp-version="${FORGEJO_MCP_VERSION}" COPY --from=broker-build /out/fjmcp-broker /usr/local/bin/fjmcp-broker COPY --from=mcp-build /out/forgejo-mcp /usr/local/bin/forgejo-mcp # Persistent volume for the SQLite store (clients, tokens, audit data). # Operators mount a named podman volume here so state survives container # replacement. SQLite WAL writes auxiliary files (.db-wal, .db-shm) next # to the main file — the volume contains them all. VOLUME ["/data"] WORKDIR /data # Distroless nonroot user is uid 65532. Volumes inherit ownership from the # host; document the chown step in deploy-podman.md. USER 65532:65532 EXPOSE 8080 ENTRYPOINT ["/usr/local/bin/fjmcp-broker"]