mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
* fix(security): bump grpcio and boto3 so their bundled CA files drop the compromised eMudhra roots grpc ignores SSL_CERT_FILE and verifies every channel against its own bundled roots.pem. In 1.78.0 that file still trusts emSign ECC Root CA - G3 and AAA Certificate Services, so Vertex AI, Google KMS, Chirp STT and OTLP gRPC exporters (Arize) accept all 14 advisory chains. 1.84.1 is the first release whose roots.pem drops both roots. botocore uses certifi when it is installed and falls back to its bundled cacert.pem otherwise. Through 1.43.116 that file still trusts AAA Certificate Services. Requiring boto3 1.43.117 pulls in botocore 1.43.117, the first release whose cacert.pem rejects all 14 advisory chains, so the fallback stays safe if certifi is ever absent * fix(docker): provide OpenSSL 3 when generating Prisma engines
149 lines
6.3 KiB
Docker
149 lines
6.3 KiB
Docker
ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:81211e15a86ea1d5357f284482af45730c51de45eaf10ad9ce205d6bfc2df323
|
|
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:81211e15a86ea1d5357f284482af45730c51de45eaf10ad9ce205d6bfc2df323
|
|
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.
|
|
# Copies only the native build's inputs, so the fat-LTO compile stays cached across Python-only changes
|
|
FROM $LITELLM_BUILD_IMAGE AS rust-native
|
|
|
|
WORKDIR /app
|
|
USER root
|
|
|
|
COPY --from=uvbin /uv /uvx /usr/local/bin/
|
|
|
|
RUN for i in 1 2 3; do \
|
|
apk add --no-cache bash gcc python-3.13 python-3.13-dev openssl openssl-dev && break; \
|
|
[ $i = 3 ] && { echo "apk add failed after 3 retries" >&2; exit 1; }; \
|
|
sleep 5; \
|
|
done
|
|
|
|
ENV UV_PYTHON_DOWNLOADS=0
|
|
|
|
COPY pyproject.toml README.md rust-toolchain.toml ./
|
|
COPY .cargo ./.cargo
|
|
COPY litellm-rust ./litellm-rust
|
|
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
mkdir -p litellm/rust_bridge /wheels && \
|
|
touch litellm/__init__.py litellm/rust_bridge/__init__.py && \
|
|
uvx --python python3.13 --from maturin==1.15.0 --with puccinialin==0.1.14 \
|
|
python -c "import maturin; maturin.build_wheel('/wheels')"
|
|
|
|
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 python-3.13 python-3.13-dev openssl libssl3 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.13
|
|
|
|
# Stage 2 — copy source and install the workspace members.
|
|
COPY . .
|
|
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
uv sync --frozen --no-install-project --no-default-groups --no-editable \
|
|
--extra proxy \
|
|
--extra extra_proxy \
|
|
--python python3.13
|
|
|
|
RUN --mount=type=bind,from=rust-native,source=/wheels,target=/wheels \
|
|
uv pip install --python /app/.venv/bin/python --no-deps /wheels/litellm-*.whl
|
|
|
|
RUN cp "$(python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])')"/litellm/rust_bridge/_native*.so litellm/rust_bridge/
|
|
|
|
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 libssl3 tzdata python-3.13 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"]
|