From db1e1b103876c36fea5fc035f2e7f831c9c903b5 Mon Sep 17 00:00:00 2001 From: clsferguson <48876201+clsferguson@users.noreply.github.com> Date: Sat, 4 Oct 2025 21:23:32 -0600 Subject: [PATCH] fix(docker): install uv system-wide so runtime works under non-root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Install uv to /usr/local/bin in both builder and runtime stages (via UV_INSTALL_DIR=/usr/local/bin, UV_NO_MODIFY_PATH=1) so the final image’s USER app can execute `uv` without relying on /root/.local/bin. This removes the permission/path mismatch that caused “exec: 'uv': not found” at startup, while preserving BuildKit cache mounts for fast `uv build`/`uv sync`. The image still installs the graphiti-core wheel first, sets PATH to include /app/.venv/bin, and runs `uv run uvicorn` on port 8000 for a clean, reproducible launch in Compose/Portainer. --- Dockerfile | 60 +++++++++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/Dockerfile b/Dockerfile index 04478e9e..0b56df04 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,87 +1,73 @@ # syntax=docker/dockerfile:1.9 -FROM python:3.12-slim as builder +# ---------- builder ---------- +FROM python:3.12-slim AS builder WORKDIR /app -# Install system dependencies for building +# Build deps RUN apt-get update && apt-get install -y --no-install-recommends \ - gcc \ - curl \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* + gcc curl ca-certificates && rm -rf /var/lib/apt/lists/* -# Install uv using the installer script -ADD https://astral.sh/uv/install.sh /uv-installer.sh -RUN sh /uv-installer.sh && rm /uv-installer.sh -ENV PATH="/root/.local/bin:$PATH" +# Install uv system-wide so any user can run it +RUN curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin UV_NO_MODIFY_PATH=1 sh -# Configure uv for optimal Docker usage +# Docker/uv performance knobs ENV UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy \ UV_PYTHON_DOWNLOADS=never -# Copy and build main graphiti-core project +# Project sources COPY ./pyproject.toml ./README.md ./ COPY ./graphiti_core ./graphiti_core -# Build graphiti-core wheel +# Build wheel (BuildKit cache) RUN --mount=type=cache,target=/root/.cache/uv \ uv build -# Install the built wheel to make it available for server +# Make wheel available to runtime RUN --mount=type=cache,target=/root/.cache/uv \ pip install dist/*.whl -# Runtime stage - build the server here + +# ---------- runtime ---------- FROM python:3.12-slim -# Install uv using the installer script +# Minimal runtime deps + uv in system path RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* + curl ca-certificates && rm -rf /var/lib/apt/lists/* -ADD https://astral.sh/uv/install.sh /uv-installer.sh -RUN sh /uv-installer.sh && rm /uv-installer.sh -ENV PATH="/root/.local/bin:$PATH" +RUN curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin UV_NO_MODIFY_PATH=1 sh -# Configure uv for runtime +# Docker/uv runtime knobs ENV UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy \ UV_PYTHON_DOWNLOADS=never -# Create non-root user +# Non-root user RUN groupadd -r app && useradd -r -d /app -g app app -# Copy graphiti-core wheel from builder +# Install core wheel first (system site) COPY --from=builder /app/dist/*.whl /tmp/ - -# Install graphiti-core wheel first RUN --mount=type=cache,target=/root/.cache/uv \ uv pip install --system /tmp/*.whl -# Set up the server application +# Server app WORKDIR /app COPY ./server/pyproject.toml ./server/README.md ./server/uv.lock ./ COPY ./server/graph_service ./graph_service -# Install server dependencies and application +# Resolve server env (creates /app/.venv) RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev -# Change ownership to app user +# Own app dir and prefer venv binaries RUN chown -R app:app /app - -# Set environment variables ENV PYTHONUNBUFFERED=1 \ PATH="/app/.venv/bin:$PATH" -# Switch to non-root user USER app - -# Set port ENV PORT=8000 -EXPOSE $PORT +EXPOSE 8000 -# Use uv run for execution +# uv is now in /usr/local/bin (on PATH) and accessible to user app CMD ["uv", "run", "uvicorn", "graph_service.main:app", "--host", "0.0.0.0", "--port", "8000"]