mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
The pinned base (built 2026-07-02) ships busybox 1.37.0-r61 and libcrypto3/libssl3 3.6.3-r3. Grype reports 16 fixable findings against those revisions, 8 of them High, so the image-scan gate fails once it gets past the migration step. The runtime stage's `apk upgrade` cannot clear them. wolfi-base writes an exact `=version` constraint for every package it ships into /etc/apk/world, so `apk upgrade` is a no-op even though the fixed revisions are in the repo. Advancing them means moving the digest. The new digest carries busybox 1.38.0-r1, libcrypto3/libssl3 3.6.3-r5 and glibc 2.43-r15, which is at or above the fix revision Wolfi's secdb records for every finding. Verified with cosign against chainguard-images/images release.yaml, and grype reports no fixable findings on the rebuilt image. CVE-2026-14456, CVE-2026-54876, CVE-2026-38752, CVE-2026-38753, CVE-2026-38754, CVE-2026-38755
118 lines
5.1 KiB
Docker
118 lines
5.1 KiB
Docker
ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72
|
|
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72
|
|
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a
|
|
|
|
FROM $UV_IMAGE AS uvbin
|
|
|
|
# ---------- Builder ----------
|
|
#
|
|
# Minimal install for `prisma migrate deploy`. We deliberately skip the heavy
|
|
# `proxy-runtime` (otel, sentry, ddtrace, pypdf, google-genai, anthropic-vertex,
|
|
# ...) and `semantic-router` extras that the gateway/backend pull in — the
|
|
# migration engine doesn't need them. We DO install `--extra proxy` so the
|
|
# DB-URL helper from `litellm.proxy.auth.rds_iam_token` is importable, which
|
|
# is how the gateway and backend assemble `DATABASE_URL` at pod startup when
|
|
# `IAM_TOKEN_DB_AUTH=true` (see backend/main.py:17, gateway/main.py:22). And
|
|
# `--extra extra_proxy` provides the `prisma` CLI + the secret-manager
|
|
# backends `litellm.secret_managers.main` lazily imports.
|
|
#
|
|
# `prisma generate` runs once at BUILD time to (a) install the Node-based
|
|
# Prisma CLI into the binary cache and (b) download the migration / query
|
|
# engine binaries. The Python client it also produces is unused by this
|
|
# image's runtime entrypoint — that's fine, it's a few hundred KB and the
|
|
# alternative (`prisma py fetch`) doesn't reliably trigger engine downloads
|
|
# under nodeenv. Crucially we do NOT run `prisma generate` at RUNTIME; the
|
|
# old migration job did, on every pod start, which is the wasteful behaviour
|
|
# the componentization is fixing.
|
|
FROM $LITELLM_BUILD_IMAGE AS builder
|
|
|
|
WORKDIR /app
|
|
USER root
|
|
|
|
COPY --from=uvbin /uv /uvx /usr/local/bin/
|
|
|
|
# nodejs/npm so `prisma generate` uses Wolfi's Node via PRISMA_USE_GLOBAL_NODE
|
|
# instead of nodeenv downloading one whose dynamic deps may not be in Wolfi
|
|
# (e.g. Node 26.2.0 needs libatomic). Retry for transient apk.cgr.dev flakes.
|
|
RUN for i in 1 2 3; do \
|
|
apk add --no-cache bash gcc python3 python3-dev openssl openssl-dev libsndfile nodejs npm && break; \
|
|
[ $i = 3 ] && { echo "apk add failed after 3 retries" >&2; exit 1; }; \
|
|
sleep 5; \
|
|
done
|
|
|
|
ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
|
UV_LINK_MODE=copy \
|
|
UV_COMPILE_BYTECODE=1 \
|
|
UV_PYTHON_DOWNLOADS=0 \
|
|
PRISMA_USE_GLOBAL_NODE=true \
|
|
PATH="/app/.venv/bin:${PATH}"
|
|
|
|
# Stage 1 — install third-party deps only (cached by pyproject.toml/uv.lock).
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
|
--mount=type=bind,source=uv.lock,target=uv.lock \
|
|
--mount=type=bind,source=enterprise/pyproject.toml,target=enterprise/pyproject.toml \
|
|
--mount=type=bind,source=litellm-proxy-extras/pyproject.toml,target=litellm-proxy-extras/pyproject.toml \
|
|
uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
|
--extra proxy \
|
|
--extra extra_proxy \
|
|
--python python3
|
|
|
|
# Stage 2 — copy source and install the project + workspace members.
|
|
COPY . .
|
|
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
uv sync --frozen --no-default-groups --no-editable \
|
|
--extra proxy \
|
|
--extra extra_proxy \
|
|
--python python3
|
|
|
|
COPY migrations/run.py /app/run.py
|
|
|
|
# Pre-warm the Prisma binary cache so the Job pod doesn't reach the
|
|
# internet on first start. This matches what the backend Dockerfile does:
|
|
# `prisma generate` runs nodeenv (downloads Node), installs the prisma npm
|
|
# CLI, downloads the engine binaries for each `binaryTarget` in
|
|
# schema.prisma, AND emits the generated Python client. We don't need the
|
|
# client at runtime — the migration job invokes `prisma migrate deploy`
|
|
# via subprocess — but having it cached is harmless and the alternative
|
|
# (`prisma py fetch`) doesn't reliably trigger engine downloads.
|
|
RUN HOME=/opt/prisma XDG_CACHE_HOME=/opt/prisma/.cache PRISMA_BINARY_CACHE_DIR=/opt/prisma/binaries \
|
|
npm_config_cache=/root/.npm \
|
|
prisma generate --schema=./schema.prisma
|
|
|
|
# ---------- Runtime ----------
|
|
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
|
|
|
USER root
|
|
|
|
RUN for i in 1 2 3; do \
|
|
apk add --no-cache bash openssl tzdata python3 nodejs libsndfile libatomic && break; \
|
|
[ $i = 3 ] && { echo "apk add failed after 3 retries" >&2; exit 1; }; \
|
|
sleep 5; \
|
|
done
|
|
|
|
# wolfi-base ships an unprivileged `nonroot` account (UID/GID 65532). The
|
|
# Prisma engine binaries are dynamically linked against libssl/libcrypto, so
|
|
# openssl stays in the runtime layer.
|
|
WORKDIR /app
|
|
ENV HOME=/home/nonroot \
|
|
PATH="/app/.venv/bin:${PATH}" \
|
|
PYTHONPATH="/app" \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
PYTHONUNBUFFERED=1 \
|
|
PRISMA_BINARY_CACHE_DIR=/opt/prisma/binaries \
|
|
PRISMA_CLI_PATH=/opt/prisma/binaries/node_modules/.bin/prisma \
|
|
PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
|
|
PRISMA_OFFLINE_MODE=true
|
|
|
|
COPY --from=builder --chown=nonroot:nonroot /app /app
|
|
COPY --from=builder /opt/prisma /opt/prisma
|
|
|
|
RUN chmod -R a+rX /opt/prisma && \
|
|
test -x /opt/prisma/binaries/node_modules/.bin/prisma && \
|
|
test -f /opt/prisma/binaries/node_modules/prisma/build/index.js
|
|
|
|
USER nonroot
|
|
|
|
ENTRYPOINT ["python3", "/app/run.py"]
|