mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
The MongoDB Atlas vector store provider imports pymongo lazily from the
opt-in `mongodb` extra, but none of the shipped images installed that
extra. Any image-based deployment that configured a MongoDB vector store
failed at search time with "requires the 'pymongo' package", which the
user cannot fix without extending the image
Adds `--extra mongodb` to every uv sync in the root Dockerfile,
Dockerfile.database, Dockerfile.non_root, and the gateway component
image. The backend component does not serve /vector_stores so it is left
as is. The extra resolves from the existing uv.lock to pymongo 4.17.0
plus dnspython 2.8.0, no lock change needed
(cherry picked from commit 16fd14f537)
203 lines
8.7 KiB
Text
203 lines
8.7 KiB
Text
# syntax=docker/dockerfile:1.7
|
|
|
|
# Base images
|
|
ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:e624c5d5e42382ce7165ddafcbbf8e6769a24cbd02ea6114b880b05ae5ba2a8d
|
|
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:e624c5d5e42382ce7165ddafcbbf8e6769a24cbd02ea6114b880b05ae5ba2a8d
|
|
ARG PROXY_EXTRAS_SOURCE=published
|
|
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a
|
|
# Pinned by digest like the other base images; bump explicitly on Node upgrades.
|
|
ARG UI_BUILD_IMAGE=node:24.19-alpine3.24@sha256:d32cdf619f63fe0471182d08996dd516c6275bb5fd31ae06e55a570bd9e1ad43
|
|
|
|
FROM $UV_IMAGE AS uvbin
|
|
|
|
# Admin UI builder. Pinned to the build platform so the architecture-independent
|
|
# Next.js static export compiles once natively even in a multi-arch build,
|
|
# instead of once per target arch under QEMU.
|
|
FROM --platform=$BUILDPLATFORM $UI_BUILD_IMAGE AS ui-builder
|
|
|
|
ENV NEXT_TELEMETRY_DISABLED=1 \
|
|
npm_config_fund=false \
|
|
npm_config_audit=false
|
|
|
|
WORKDIR /ui
|
|
|
|
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
|
|
|
|
FROM $LITELLM_BUILD_IMAGE AS builder
|
|
ARG PROXY_EXTRAS_SOURCE
|
|
WORKDIR /app
|
|
USER root
|
|
|
|
COPY --from=uvbin /uv /usr/local/bin/uv
|
|
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
|
|
|
RUN for i in 1 2 3; do \
|
|
apk add --no-cache \
|
|
python-3.13 \
|
|
python-3.13-dev \
|
|
gcc \
|
|
rust \
|
|
bash \
|
|
coreutils \
|
|
curl \
|
|
openssl \
|
|
libsndfile \
|
|
nodejs \
|
|
npm && break || sleep 5; \
|
|
done
|
|
|
|
ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
|
UV_LINK_MODE=copy \
|
|
UV_PYTHON_DOWNLOADS=0 \
|
|
PATH="/app/.venv/bin:${PATH}" \
|
|
LITELLM_NON_ROOT=true \
|
|
XDG_CACHE_HOME=/app/.cache
|
|
|
|
# Copy dependency metadata first for layer caching
|
|
COPY pyproject.toml uv.lock ./
|
|
COPY enterprise/pyproject.toml enterprise/
|
|
COPY litellm-proxy-extras/pyproject.toml litellm-proxy-extras/
|
|
|
|
# Install third-party dependencies (cached unless pyproject.toml/uv.lock change)
|
|
RUN --mount=type=cache,target=/app/.cache/uv,id=litellm-uv-cache \
|
|
uv sync --frozen --no-install-project --no-install-workspace --no-default-groups --no-editable \
|
|
--extra proxy \
|
|
--extra proxy-runtime \
|
|
--extra extra_proxy \
|
|
--extra semantic-router \
|
|
--extra saml \
|
|
--extra bedrock-realtime \
|
|
--extra mongodb \
|
|
--python python3.13
|
|
|
|
# Copy full source tree
|
|
COPY . .
|
|
|
|
# Replace the committed UI bundle with the one built from this exact source.
|
|
# Clearing first drops the committed bundle's content-hashed chunks that COPY
|
|
# would otherwise leave behind alongside the fresh ones.
|
|
RUN rm -rf litellm/proxy/_experimental/out
|
|
COPY --from=ui-builder /ui/out/. litellm/proxy/_experimental/out/
|
|
|
|
# Set non-root flag for build time consistency
|
|
ENV LITELLM_NON_ROOT=true
|
|
|
|
RUN mkdir -p /var/lib/litellm/ui /var/lib/litellm/assets && \
|
|
cp -r /app/litellm/proxy/_experimental/out/. /var/lib/litellm/ui/ && \
|
|
cp /app/litellm/proxy/logo.jpg /var/lib/litellm/assets/logo.jpg && \
|
|
touch /var/lib/litellm/ui/.litellm_ui_ready
|
|
|
|
RUN --mount=type=cache,target=/app/.cache/uv,id=litellm-uv-cache \
|
|
if [ "$PROXY_EXTRAS_SOURCE" = "published" ]; then \
|
|
uv sync --frozen --no-default-groups --no-editable \
|
|
--extra proxy \
|
|
--extra proxy-runtime \
|
|
--extra extra_proxy \
|
|
--extra semantic-router \
|
|
--extra saml \
|
|
--extra bedrock-realtime \
|
|
--extra mongodb \
|
|
--python python3.13 \
|
|
--no-sources-package litellm-proxy-extras; \
|
|
else \
|
|
uv sync --frozen --no-default-groups --no-editable \
|
|
--extra proxy \
|
|
--extra proxy-runtime \
|
|
--extra extra_proxy \
|
|
--extra semantic-router \
|
|
--extra saml \
|
|
--extra bedrock-realtime \
|
|
--extra mongodb \
|
|
--python python3.13; \
|
|
fi
|
|
|
|
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
|
|
|
|
RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh && \
|
|
sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh
|
|
|
|
FROM $LITELLM_RUNTIME_IMAGE AS runtime
|
|
ARG PROXY_EXTRAS_SOURCE
|
|
WORKDIR /app
|
|
USER root
|
|
|
|
RUN for i in 1 2 3; do \
|
|
apk upgrade --no-cache && break || sleep 5; \
|
|
done && \
|
|
for i in 1 2 3; do \
|
|
apk add --no-cache python-3.13 bash openssl tzdata libsndfile nodejs && break || sleep 5; \
|
|
done
|
|
|
|
# Copy only what runtime needs. The application is installed inside the venv;
|
|
# the rest of the builder's /app is source and build metadata that must not
|
|
# ship (manifest-scanning tools attribute everything in it to this image).
|
|
# entrypoint.sh invokes litellm/proxy/prisma_migration.py by source path.
|
|
COPY --from=builder /app/.venv /app/.venv
|
|
COPY --from=builder /app/docker /app/docker
|
|
COPY --from=builder /app/schema.prisma /app/schema.prisma
|
|
COPY --from=builder /app/litellm/proxy/prisma_migration.py /app/litellm/proxy/prisma_migration.py
|
|
# enterprise/ is imported by source path at runtime (proxy_cli puts the
|
|
# working directory on sys.path; litellm/proxy/hooks resolves
|
|
# enterprise.enterprise_hooks from it)
|
|
COPY --from=builder /app/enterprise /app/enterprise
|
|
COPY --from=builder /app/litellm-proxy-extras /app/litellm-proxy-extras
|
|
# Prisma CLI + engines are baked under /opt/prisma, a fixed path every runtime
|
|
# uid can read and that no cache volume mount shadows (unlike /app/.cache or
|
|
# $HOME/.cache under readOnlyRootFilesystem + emptyDir or arbitrary-uid setups).
|
|
# PRISMA_CLI_QUERY_ENGINE_TYPE=binary makes the CLI use the baked binary query
|
|
# engine directly, so `prisma migrate deploy` on a fresh database needs no npm
|
|
# and no network access; without it the CLI looks for the library engine, which
|
|
# prisma stopped baking, and falls back to a download that fails offline or as a
|
|
# non-writable uid (#33650, #24554).
|
|
COPY --from=builder /opt/prisma /opt/prisma
|
|
COPY --from=builder /var/lib/litellm/ui /var/lib/litellm/ui
|
|
COPY --from=builder /var/lib/litellm/assets /var/lib/litellm/assets
|
|
|
|
# XDG_CACHE_HOME is intentionally left unset so it falls back to $HOME/.cache
|
|
# (/app/.cache, writable by the runtime uid). The prisma bake at the read-only
|
|
# /opt/prisma is anchored by PRISMA_BINARY_CACHE_DIR / PRISMA_CLI_PATH, so
|
|
# nothing needs XDG to point there; pointing it at the read-only bake would
|
|
# deny any XDG-aware library that writes a cache at runtime.
|
|
ENV PATH="/app/.venv/bin:${PATH}" \
|
|
PRISMA_BINARY_CACHE_DIR=/opt/prisma/binaries \
|
|
PRISMA_CLI_PATH=/opt/prisma/binaries/node_modules/.bin/prisma \
|
|
PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
|
|
HOME=/app \
|
|
LITELLM_NON_ROOT=true \
|
|
PRISMA_SKIP_POSTINSTALL_GENERATE=1 \
|
|
PRISMA_HIDE_UPDATE_MESSAGE=1 \
|
|
PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1 \
|
|
PRISMA_OFFLINE_MODE=true
|
|
|
|
RUN mkdir -p /nonexistent /app/.cache /var/lib/litellm/assets /var/lib/litellm/ui && \
|
|
chown -R nobody:nogroup /app /var/lib/litellm/ui /var/lib/litellm/assets /nonexistent && \
|
|
PRISMA_PATH=$(python -c "import os, prisma; print(os.path.dirname(prisma.__file__))") && \
|
|
chown -R nobody:nogroup "$PRISMA_PATH" && \
|
|
LITELLM_PKG_MIGRATIONS_PATH="$(python -c 'import os, litellm_proxy_extras; print(os.path.dirname(litellm_proxy_extras.__file__))' 2>/dev/null || echo '')/migrations" && \
|
|
[ -n "$LITELLM_PKG_MIGRATIONS_PATH" ] && chown -R nobody:nogroup "$LITELLM_PKG_MIGRATIONS_PATH" || true && \
|
|
LITELLM_PROXY_EXTRAS_PATH=$(python -c "import os, litellm_proxy_extras; print(os.path.dirname(litellm_proxy_extras.__file__))" 2>/dev/null || echo "") && \
|
|
chgrp -R 0 "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets && \
|
|
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chgrp -R 0 "$LITELLM_PROXY_EXTRAS_PATH" || true && \
|
|
chmod -R g=u "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets && \
|
|
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g=u "$LITELLM_PROXY_EXTRAS_PATH" || true && \
|
|
chmod -R g+w "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets && \
|
|
[ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g+w "$LITELLM_PROXY_EXTRAS_PATH" || true && \
|
|
chmod -R g+rX "$PRISMA_PATH" /var/lib/litellm/ui /var/lib/litellm/assets && \
|
|
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 && \
|
|
ls /opt/prisma/binaries/node_modules/@prisma/engines/query-engine-* >/dev/null 2>&1 && \
|
|
python -c "from prisma.client import BINARY_PATHS; paths = list(BINARY_PATHS.query_engine.values()); assert paths and all(p.startswith('/opt/prisma/') for p in paths), paths"
|
|
|
|
USER 65534
|
|
|
|
EXPOSE 4000/tcp
|
|
|
|
ENTRYPOINT ["/app/docker/prod_entrypoint.sh"]
|
|
CMD ["--port", "4000"]
|