# syntax=docker/dockerfile:1 # Frontend build stage # Build frontend assets on the native build platform to avoid # cross-architecture emulation issues during multi-platform builds. FROM --platform=$BUILDPLATFORM oven/bun:1 AS frontend-builder WORKDIR /app # Copy frontend source code COPY lightrag_webui/ ./lightrag_webui/ # Build frontend assets for inclusion in the API package RUN --mount=type=cache,target=/root/.bun/install/cache \ cd lightrag_webui \ && bun install --frozen-lockfile \ && bun run build # Python build stage - using uv for faster package installation FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder ENV DEBIAN_FRONTEND=noninteractive ENV UV_SYSTEM_PYTHON=1 ENV UV_COMPILE_BYTECODE=1 WORKDIR /app # Install system deps (Rust is required by some wheels) RUN apt-get update \ && apt-get install -y --no-install-recommends \ curl \ build-essential \ pkg-config \ && rm -rf /var/lib/apt/lists/* \ && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH="/root/.cargo/bin:/root/.local/bin:${PATH}" # Ensure shared data directory exists for uv caches RUN mkdir -p /root/.local/share/uv # Copy project metadata and sources COPY pyproject.toml . COPY setup.py . COPY uv.lock . # Install base, API, and offline extras without the project to improve caching RUN --mount=type=cache,target=/root/.local/share/uv \ uv sync --frozen --no-dev --extra api --extra offline --no-install-project --no-editable # Copy project sources after dependency layer COPY lightrag/ ./lightrag/ # Include pre-built frontend assets from the previous stage COPY --from=frontend-builder /app/lightrag/api/webui ./lightrag/api/webui # Sync project in non-editable mode and ensure pip is available for runtime installs RUN --mount=type=cache,target=/root/.local/share/uv \ uv sync --frozen --no-dev --extra api --extra offline --no-editable \ && /app/.venv/bin/python -m ensurepip --upgrade # Prepare offline cache directory and pre-populate tiktoken data # Use uv run to execute commands from the virtual environment RUN mkdir -p /app/data/tiktoken \ && uv run lightrag-download-cache --cache-dir /app/data/tiktoken || status=$?; \ if [ -n "${status:-}" ] && [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then exit "$status"; fi # Final stage # Pin to bookworm: keeps Python 3.12 (venv compat with the builder stage) while # avoiding Debian trixie's perl 5.40.x exposure (CVE-2026-12087, no patch yet), # and aligns the final Debian release with the builder (also bookworm). FROM python:3.12-slim-bookworm WORKDIR /app # Install uv for package management COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv ENV UV_SYSTEM_PYTHON=1 # Copy installed packages and application code COPY --from=builder /root/.local /root/.local COPY --from=builder /app/.venv /app/.venv COPY --from=builder /app/lightrag ./lightrag COPY pyproject.toml . COPY setup.py . COPY uv.lock . # Ensure the installed scripts are on PATH ENV PATH=/app/.venv/bin:/root/.local/bin:$PATH # Install dependencies with uv sync (uses locked versions from uv.lock) # And ensure pip is available for runtime installs RUN --mount=type=cache,target=/root/.local/share/uv \ uv sync --frozen --no-dev --extra api --extra offline --no-editable \ && /app/.venv/bin/python -m ensurepip --upgrade # Create persistent data directories AFTER package installation RUN mkdir -p /app/data/rag_storage /app/data/inputs /app/data/prompts /app/data/tiktoken # Copy offline cache into the newly created directory COPY --from=builder /app/data/tiktoken /app/data/tiktoken # Point to the prepared cache ENV TIKTOKEN_CACHE_DIR=/app/data/tiktoken ENV WORKING_DIR=/app/data/rag_storage ENV INPUT_DIR=/app/data/inputs ENV PROMPT_DIR=/app/data/prompts # Create a non-root user (CIS Docker 4.1) and install gosu for privilege drop. # Fixed UID/GID 1000 gives predictable ownership for bind-mounts / PVCs. # chown -R /app MUST run after every data COPY above so the venv (pipmaster # installs packages at runtime), data dirs, and the tiktoken cache are writable. RUN apt-get update \ && apt-get install -y --no-install-recommends gosu \ && rm -rf /var/lib/apt/lists/* \ && groupadd -g 1000 lightrag \ && useradd -u 1000 -g lightrag -m -d /home/lightrag -s /usr/sbin/nologin lightrag \ && chown -R lightrag:lightrag /app /home/lightrag # HOME and cache dirs for the non-root user so pipmaster's runtime pip installs # never fall back to an unwritable /root or a missing HOME. ENV HOME=/home/lightrag \ XDG_CACHE_HOME=/home/lightrag/.cache \ PIP_CACHE_DIR=/home/lightrag/.cache/pip \ UV_CACHE_DIR=/home/lightrag/.cache/uv # Entrypoint starts as root, fixes mount ownership, then drops to lightrag. COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh RUN chmod +x /usr/local/bin/docker-entrypoint.sh # Expose API port EXPOSE 9621 ENTRYPOINT ["docker-entrypoint.sh"] CMD ["python", "-m", "lightrag.api.lightrag_server"]