# syntax=docker/dockerfile:1 # ════════════════════════════════════════════════ # Build stage: install production deps via uv # ════════════════════════════════════════════════ FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder WORKDIR /app ENV UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy \ UV_PYTHON_DOWNLOADS=never # Layer cache split: deps only (changes rarely) COPY pyproject.toml uv.lock ./ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --no-install-project # Layer cache split: source (changes often) COPY app/ ./app/ # ════════════════════════════════════════════════ # Runtime stage: lean image with venv + source # ════════════════════════════════════════════════ FROM python:3.12-slim WORKDIR /app RUN apt-get update \ && apt-get install -y --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/* RUN groupadd --system --gid 1001 appgroup \ && useradd --system --uid 1001 --gid 1001 --no-create-home appuser COPY --from=builder --chown=appuser:appgroup /app/.venv /app/.venv COPY --chown=appuser:appgroup app/ ./app/ USER appuser ENV PATH="/app/.venv/bin:$PATH" EXPOSE 8000 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD curl -f http://localhost:8000/api/v1/health || exit 1 CMD ["uvicorn", "app.main:app", \ "--host", "0.0.0.0", \ "--port", "8000", \ "--timeout-graceful-shutdown", "30"]