# 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"]
