# ---- Base stage: shared dependencies ---- FROM python:3.13-slim AS base ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy COPY --from=ghcr.io/astral-sh/uv:0.11.29 /uv /uvx /bin/ WORKDIR /app # Install production dependencies (cached unless lock changes) COPY pyproject.toml uv.lock ./ RUN uv sync --frozen --no-install-project --no-dev # ---- Dev stage: hot-reload for local development ---- FROM base AS dev # Also install dev dependencies. The project source is bind-mounted at runtime. RUN uv sync --frozen --no-install-project # Source is bind-mounted at runtime via docker-compose ENV OIDC_OP_ISSUER=http://localhost:8000 \ OIDC_OP_DEBUG=true \ OIDC_OP_SESSION_HTTPS_ONLY=false \ PATH="/app/.venv/bin:$PATH" \ PYTHONPATH=/app/src EXPOSE 8000 CMD ["uvicorn", "porchlight.app:create_app", \ "--factory", "--host", "0.0.0.0", "--port", "8000", \ "--reload", "--reload-dir", "/app/src"] # ---- Prod stage: optimised image ---- FROM base AS prod # Copy source + README (needed by hatchling) and install the project itself COPY README.md ./ COPY src/ src/ RUN uv sync --frozen --no-dev # Use the venv built above directly — avoids `uv run` re-syncing (and # needing network access to re-resolve/rebuild) at container startup. ENV PATH="/app/.venv/bin:$PATH" RUN groupadd --system porchlight \ && useradd --system --gid porchlight --home-dir /app porchlight \ && mkdir -p /app/data \ && chown porchlight:porchlight /app/data \ && mkdir -p /app/config \ && chown porchlight:porchlight /app/config USER porchlight EXPOSE 8000 CMD ["uvicorn", "porchlight.app:create_app", \ "--factory", "--host", "0.0.0.0", "--port", "8000", \ "--workers", "4"]