Files
stack/infra/images/llm.Dockerfile
kert c0ce3524b6 fix(images): trixie bases, locked syncs, no system pip; mc sidecar runs RustFS's rc
Base images
- api, llm, docs(extract), notebooks(wheel): uv:python3.13-bookworm-slim
  -> uv:0.13.2-python3.13-trixie-slim. Debian 12 left regular security
  support in June 2026; a pinned uv tag makes base changes a reviewed
  diff Renovate can bump. notebooks copies /uv from the same tag
  instead of uv:latest.
- api, llm: `uv sync --locked` — a stale lock now fails the build
  instead of silently re-resolving to packages pkg-supply-chain never
  scanned.
- api, llm: uninstall the base image's system pip. Nothing runs it (uv
  owns the venv), and its vendored certifi/urllib3/msgpack/setuptools
  were the image's only language-level findings.
- notebooks: the workspace resolves at build time with no committed
  lock, so it gets the same 7-day cooldown via ENV UV_EXCLUDE_NEWER
  (ENV, not a prefix — the recorded span must match at `uv run` time).
- docs: pnpm 10.12.1 -> 10.34.7 to match packageManager.

trivy HIGH/CRITICAL, deployed image -> this build:
  api   11 crit / 94 high -> 0 / 48
  llm    9 / 129          -> 1 / 70
  docs   0 / 38           -> 0 / 0
  mc     2 / 52           -> 0 / 0
What's left is Debian `affected` with no fix released (libxml2 is the
llm critical); the weekly Harden --pull rebuild picks fixes up as they
land.

mc sidecar
MinIO archived the open-source client: quay.io/minio/mc answers 401,
dl.min.io 410 Gone, and there are no more security fixes. The service
keeps its name but ships rustfs/rc v0.1.36 on alpine:3.24 — same alias
grammar (RC_HOST_local=http://key:secret@rustfs:9000), same admin verbs
(`docker exec mc rc admin policy create local/ <name> <file>`), same
hardening (uid 10002, read-only root, no caps). Verified against the
live RustFS: `rc ls local/` lists all six buckets, `rc admin user list`
reaches the admin API. Config dir moves to a tmpfs at
/home/mc/.config/rc.

Refs #1365
2026-10-27 11:04:28 -04:00

46 lines
1.8 KiB
Docker

# syntax=docker/dockerfile:1
FROM ghcr.io/astral-sh/uv:0.13.2-python3.13-trixie-slim
WORKDIR /app
# Local package registry (Gitea) — set via --build-arg to pull from mirror
ARG PYPI_INDEX_URL=""
# Patch base image CVEs + install curl for the healthcheck.
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
# uv manages the venv; the base image's system pip is never used, and its
# vendored certifi/urllib3/msgpack/setuptools copies lag and get flagged.
RUN python3 -m pip uninstall -y -q pip
# Word → PDF for the document viewer (llm.convert): headless Writer plus
# metric-compatible fonts so Calibri/Cambria/Times/Arial letters paginate
# like Word (Carlito, Caladea, Liberation) — no X, no Java.
RUN apt-get update && apt-get install -y --no-install-recommends \
libreoffice-writer-nogui fonts-crosextra-carlito fonts-crosextra-caladea \
fonts-liberation2 fonts-dejavu-core \
&& rm -rf /var/lib/apt/lists/*
COPY pyproject.toml uv.lock README.md ./
COPY src/ src/
# The chat service needs the `llm` extra (fastapi/uvicorn/langchain/pgvector).
ENV UV_PYTHON_PREFERENCE=only-system \
UV_LINK_MODE=copy \
UV_PROJECT_ENVIRONMENT=.venv \
UV_INDEX_URL=${PYPI_INDEX_URL}
# --locked: a stale uv.lock fails the build instead of silently re-resolving
# to packages nobody scanned (pkg-supply-chain scans uv.lock).
RUN uv sync --locked --no-dev --extra llm --extra perf && uv pip install -e .
# Config (conf reads stack.toml by walking up from CWD)
COPY stack.toml ./
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -sf --max-time 4 http://localhost:8000/health || exit 1
CMD ["uv", "run", "--no-sync", "uvicorn", "llm.api:app", \
"--host", "0.0.0.0", "--port", "8000", \
"--workers", "1", "--log-level", "info"]