litellm/ui/Dockerfile
Yuneng Jiang dd8605cff0
chore(build): move the UI image's nginx to 1.31.3 and pin it by digest
The runtime stage tracked nginx 1.27, a mainline line that upstream stopped
maintaining once 1.29 landed, so it no longer picks up any upstream fixes.
Move to 1.31.3-alpine3.24, which keeps the image on the mainline line it
already followed and brings the Alpine base in line with the Node 24
builder stage above it.

Pin the ref by digest and fold it into a UI_RUNTIME_IMAGE arg, matching how
UI_BUILD_IMAGE already carries a full digest-pinned ref. A floating
1.31-alpine tag would have resolved to 1.31.4, published earlier today, and
the digest pin keeps the image reproducible instead of drifting whenever
upstream rebuilds the tag.

Verified by building the runtime stage against both the old and new bases
from a byte-identical static export: the config parses on both and all 17
probed routes match on status, content type, cache headers, gzip
negotiation, and body hash. The only response delta is the nginx version
string in the Server header and the built-in 404 page.
2026-08-19 13:29:19 -07:00

42 lines
1.3 KiB
Docker

# syntax=docker/dockerfile:1.7
# UI container — Next.js static export served by nginx.
ARG UI_BUILD_IMAGE=node:24.19-alpine3.24@sha256:d32cdf619f63fe0471182d08996dd516c6275bb5fd31ae06e55a570bd9e1ad43
ARG UI_RUNTIME_IMAGE=nginx:1.31.3-alpine3.24@sha256:4a73073bd557c65b759505da037898b61f1be6cbcc3c2c3aeac22d2a470c1752
# ---------- builder ----------
FROM ${UI_BUILD_IMAGE} AS builder
ENV NEXT_TELEMETRY_DISABLED=1 \
npm_config_fund=false \
npm_config_audit=false
WORKDIR /app
# Layer the lockfile-only install above the source copy so source-only
# edits don't bust the install cache.
COPY ui/litellm-dashboard/package.json ui/litellm-dashboard/package-lock.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci --prefer-offline
COPY ui/litellm-dashboard/ ./
RUN npm run build
# ---------- runtime ----------
FROM ${UI_RUNTIME_IMAGE} AS runtime
# Drop the upstream default :80 server; we own the config.
RUN rm -f /etc/nginx/conf.d/default.conf
# Static export → web root.
COPY --from=builder /app/out /usr/share/nginx/html
# Routing rules — see ui/nginx.conf for the full description.
COPY ui/nginx.conf /etc/nginx/nginx.conf
EXPOSE 3000/tcp
# nginx as PID 1 in foreground; respects SIGTERM out of the box, so
# no tini/dumb-init wrapper needed.
CMD ["nginx", "-g", "daemon off;"]