# Base images ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base # ----------------- # Builder Stage # ----------------- FROM $LITELLM_BUILD_IMAGE AS builder WORKDIR /app # Install build dependencies including Node.js for UI build USER root RUN apk add --no-cache \ python3 \ py3-pip \ clang \ llvm \ lld \ gcc \ linux-headers \ build-base \ bash \ nodejs \ npm \ && pip install --no-cache-dir --upgrade pip build # Copy project files COPY . . # Set LITELLM_NON_ROOT flag for build time ENV LITELLM_NON_ROOT=true # Build Admin UI RUN mkdir -p /tmp/litellm_ui RUN npm install -g npm@latest && npm cache clean --force RUN cd /app/ui/litellm-dashboard && \ if [ -f "/app/enterprise/enterprise_ui/enterprise_colors.json" ]; then \ cp /app/enterprise/enterprise_ui/enterprise_colors.json ./ui_colors.json; \ fi RUN cd /app/ui/litellm-dashboard && rm -f package-lock.json RUN cd /app/ui/litellm-dashboard && npm install --legacy-peer-deps RUN cd /app/ui/litellm-dashboard && npm run build RUN cp -r /app/ui/litellm-dashboard/out/* /tmp/litellm_ui/ RUN cd /tmp/litellm_ui && \ for html_file in *.html; do \ if [ "$html_file" != "index.html" ] && [ -f "$html_file" ]; then \ folder_name="${html_file%.html}" && \ mkdir -p "$folder_name" && \ mv "$html_file" "$folder_name/index.html"; \ fi; \ done RUN cd /app/ui/litellm-dashboard && rm -rf ./out # Build package and wheel dependencies RUN rm -rf dist/* && python -m build && \ pip install dist/*.whl && \ pip wheel --no-cache-dir --wheel-dir=/wheels/ -r requirements.txt # ----------------- # Runtime Stage # ----------------- FROM $LITELLM_RUNTIME_IMAGE AS runtime WORKDIR /app # Install runtime dependencies USER root RUN apk upgrade --no-cache && \ apk add --no-cache python3 py3-pip bash openssl tzdata nodejs npm supervisor # Copy only necessary artifacts from builder stage for runtime COPY . . COPY --from=builder /app/docker/entrypoint.sh /app/docker/prod_entrypoint.sh /app/docker/ COPY --from=builder /app/docker/supervisord.conf /etc/supervisord.conf COPY --from=builder /app/schema.prisma /app/schema.prisma COPY --from=builder /app/dist/*.whl . COPY --from=builder /wheels/ /wheels/ COPY --from=builder /tmp/litellm_ui /tmp/litellm_ui # Install package from wheel and dependencies RUN pip install *.whl /wheels/* --no-index --find-links=/wheels/ \ && rm -f *.whl \ && rm -rf /wheels # Remove test files and keys from dependencies RUN find /usr/lib -type f -path "*/tornado/test/*" -delete && \ find /usr/lib -type d -path "*/tornado/test" -delete # Install semantic_router and aurelio-sdk using script RUN chmod +x docker/install_auto_router.sh && ./docker/install_auto_router.sh # Ensure correct JWT library is used (pyjwt not jwt) RUN pip uninstall jwt -y && \ pip uninstall PyJWT -y && \ pip install PyJWT==2.9.0 --no-cache-dir # Set Prisma cache directories ENV PRISMA_BINARY_CACHE_DIR=/nonexistent ENV NPM_CONFIG_CACHE=/.npm # Install prisma and make entrypoints executable RUN pip install --no-cache-dir prisma && \ chmod +x docker/entrypoint.sh && \ chmod +x docker/prod_entrypoint.sh # Create directories and set permissions for non-root user RUN mkdir -p /nonexistent /.npm && \ chown -R nobody:nogroup /app /tmp/litellm_ui /nonexistent /.npm && \ 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 # OpenShift compatibility RUN PRISMA_PATH=$(python -c "import os, prisma; print(os.path.dirname(prisma.__file__))") && \ 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 /tmp/litellm_ui && \ [ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chgrp -R 0 $LITELLM_PROXY_EXTRAS_PATH || true && \ chmod -R g=u $PRISMA_PATH /tmp/litellm_ui && \ [ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g=u $LITELLM_PROXY_EXTRAS_PATH || true && \ chmod -R g+w $PRISMA_PATH /tmp/litellm_ui && \ [ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g+w $LITELLM_PROXY_EXTRAS_PATH || true # Switch to non-root user USER nobody # Set HOME for prisma generate to have a writable directory ENV HOME=/app # Set LITELLM_NON_ROOT flag for runtime ENV LITELLM_NON_ROOT=true RUN prisma generate EXPOSE 4000/tcp ENTRYPOINT ["/app/docker/prod_entrypoint.sh"] CMD ["--port", "4000"]