# The llmgw control plane as a container image, for deploy/helm/llmgw. # # The project publishes binaries, not an image, so this is built where the # image is to live: # # docker build -f deploy/container/Dockerfile --build-arg VERSION=v0.11.1 \ # -t registry.internal/llmgw:v0.11.1 . # docker push registry.internal/llmgw:v0.11.1 # # The binary is static (CGO_ENABLED=0, as every release is), so the image is # that one file on a base with nothing else in it: no shell, no package # manager. `kubectl exec ... -- llmgw ctl status` still works, because it # runs the binary rather than a shell. # # Only the control plane runs from it. An agent installs engines on its # machine, manages its GPUs and supervises processes there as root, which is # what a container is built to prevent: docs/kubernetes.md. FROM golang:1.26 AS build WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . ARG VERSION=dev RUN CGO_ENABLED=0 go build -trimpath \ -ldflags "-s -w -X gitea.mynodes.xyz/ilker/llmgw/internal/version.Version=${VERSION}" \ -o /out/llmgw ./cmd/llmgw && \ mkdir -p /out/state FROM gcr.io/distroless/static-debian12:nonroot COPY --from=build /out/llmgw /usr/local/bin/llmgw # The chart mounts server.yaml, the certificates and the token under # /etc/llmgw, and the SQLite store, when it is one, under /var/lib/llmgw — # owned by the user the server runs as, so a volume Docker fills from the # image is writable without Kubernetes' fsGroup. COPY --from=build --chown=65532:65532 /out/state /var/lib/llmgw USER 65532:65532 EXPOSE 8080 7443 9091 ENTRYPOINT ["/usr/local/bin/llmgw"] CMD ["server", "--config", "/etc/llmgw/server.yaml"]