diff --git a/serving/fleet-manager/Dockerfile b/serving/fleet-manager/Dockerfile new file mode 100644 index 0000000..ec267d2 --- /dev/null +++ b/serving/fleet-manager/Dockerfile @@ -0,0 +1,35 @@ +# fleet-manager — server-side fleet control plane + embedded admin SPA. +# +# Two stages: build the Svelte SPA (node) → dist/, then compile the Go binary +# with the SPA embedded (`-tags embedspa`). The gRPC .pb.go stubs are committed, +# so no protoc is needed here. Ships as a small static distroless image; the same +# binary also serves the `register-admin` subcommand. +# +# docker build -t fleet-manager serving/fleet-manager + +# ---- 1. build the SPA ------------------------------------------------------ +FROM node:24-alpine AS ui +WORKDIR /ui +COPY ui/package.json ui/package-lock.json ./ +RUN npm ci --no-audit --no-fund +COPY ui/ ./ +RUN npm run build # -> /ui/dist + +# ---- 2. build the Go binary (SPA embedded) -------------------------------- +FROM golang:1.26-alpine AS build +WORKDIR /src +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +COPY --from=ui /ui/dist ./ui/dist +ENV CGO_ENABLED=0 GOTOOLCHAIN=local +RUN go build -tags embedspa -trimpath -buildvcs=false \ + -ldflags '-s -w -buildid=' -o /fleet-manager . + +# ---- 3. minimal runtime ---------------------------------------------------- +# distroless/static: static binary + ca-certificates + tzdata, non-root by +# default. The data dir (inventory + admin store) is a mounted, writable volume. +FROM gcr.io/distroless/static-debian12:nonroot +COPY --from=build /fleet-manager /usr/local/bin/fleet-manager +USER nonroot:nonroot +ENTRYPOINT ["/usr/local/bin/fleet-manager"]