mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-08 13:12:16 +00:00
1fd8ab4c5f
* fix(docker): copy only runtime artifacts into the final image The runtime stage previously copied the builder's entire /app workspace, shipping the full source tree and dependency manifests (uv.lock, the dashboard package-lock.json, ui/) in the published images. Tools that read manifests found in an image attribute every pin in them to the image, including packages that are never installed, which produces recurring false reports against the official images. The runtime stage now copies an explicit allowlist: the venv (where the application is installed), the entrypoint scripts, schema.prisma, prisma_migration.py (invoked by source path from entrypoint.sh), and the prisma binary caches. npm and its globally installed helper packages are dropped from the runtime stage; node stays for the prisma CLI. The database image's /root/.cache copy is narrowed to the prisma subdirs, matching the main Dockerfile, which removes the uv build cache from that image (-1.1GB). Verified on locally built images for all three variants against a contract suite that passes 100% on the v1.88.1 baselines: byte-identical venv vs old-Dockerfile builds from the same commit, DB-less and Postgres-backed boots, migration entrypoint, real completion and streaming calls, admin UI, key generation, non-root UID behavior. Image sizes: main 1.71GB -> 1.53GB, database 2.68GB -> 1.53GB * fix(docker): restore enterprise source dir required by runtime imports litellm/proxy/hooks/__init__.py, callback_utils.py and customer_endpoints.py import enterprise.* by source path, resolved via the cwd entry proxy_cli appends to sys.path, with silent ImportError fallbacks. Dropping /app/enterprise from the runtime image emptied ENTERPRISE_PROXY_HOOKS and broke managed files (e2e_openai_endpoints caught it). Restore the directory in all three runtime stages
102 lines
3.6 KiB
Docker
102 lines
3.6 KiB
Docker
# Base image for building
|
|
ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:3258be472764337fd13095bcbb3182da170243b5819fd67ad4c0754590588b31
|
|
|
|
# Runtime image
|
|
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:3258be472764337fd13095bcbb3182da170243b5819fd67ad4c0754590588b31
|
|
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a
|
|
|
|
FROM $UV_IMAGE AS uvbin
|
|
|
|
FROM $LITELLM_BUILD_IMAGE AS builder
|
|
|
|
WORKDIR /app
|
|
USER root
|
|
|
|
COPY --from=uvbin /uv /usr/local/bin/uv
|
|
COPY --from=uvbin /uvx /usr/local/bin/uvx
|
|
|
|
RUN apk add --no-cache \
|
|
bash \
|
|
gcc \
|
|
python3 \
|
|
python3-dev \
|
|
openssl \
|
|
openssl-dev \
|
|
nodejs \
|
|
npm \
|
|
libsndfile
|
|
|
|
ENV UV_PROJECT_ENVIRONMENT=/app/.venv \
|
|
UV_LINK_MODE=copy \
|
|
PATH="/app/.venv/bin:${PATH}"
|
|
|
|
# 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 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 \
|
|
--python python3
|
|
|
|
# Copy full source tree
|
|
COPY . .
|
|
|
|
# Build Admin UI before final sync
|
|
RUN sed -i 's/\r$//' docker/build_admin_ui.sh && chmod +x docker/build_admin_ui.sh && ./docker/build_admin_ui.sh
|
|
|
|
# Install project and workspace packages (fast - deps already cached)
|
|
RUN uv sync --frozen --no-default-groups --no-editable \
|
|
--extra proxy \
|
|
--extra proxy-runtime \
|
|
--extra extra_proxy \
|
|
--extra semantic-router \
|
|
--python python3
|
|
|
|
RUN 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
|
|
|
|
USER root
|
|
|
|
# node (without npm) is required by the prisma CLI at runtime
|
|
RUN apk add --no-cache bash openssl tzdata nodejs python3 libsndfile
|
|
|
|
WORKDIR /app
|
|
ENV PATH="/app/.venv/bin:${PATH}"
|
|
|
|
# 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
|
|
# Prisma binaries live in $HOME/.cache (default prisma-python location),
|
|
# which is /root/.cache here. Copy them from the builder so they survive
|
|
# deployments that volume-mount /app/.cache (e.g. readOnlyRootFilesystem
|
|
# + emptyDir) — otherwise the mount would shadow the baked-in query engine.
|
|
# Only the Prisma subdirs: the whole /root/.cache drags in the uv build cache.
|
|
COPY --from=builder /root/.cache/prisma /root/.cache/prisma
|
|
COPY --from=builder /root/.cache/prisma-python /root/.cache/prisma-python
|
|
|
|
RUN find /app/.venv -type f -path "*/tornado/test/*" -delete && \
|
|
find /app/.venv -type d -path "*/tornado/test" -delete
|
|
|
|
EXPOSE 4000/tcp
|
|
|
|
ENTRYPOINT ["docker/prod_entrypoint.sh"]
|
|
CMD ["--port", "4000"]
|