# syntax=docker/dockerfile:1.7 # ============================================================================ # Build stage: create a self-contained venv with all dependencies # ============================================================================ FROM python:3.11-slim-bookworm AS builder ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 # --copies bundles the Python binary itself into /opt/venv so the runtime # stage gets a self-contained tree (no symlinks back to /usr/local/bin). RUN python -m venv --copies /opt/venv ENV PATH=/opt/venv/bin:$PATH # Install runtime deps into the venv's site-packages RUN pip install \ fastapi==0.115.* \ "uvicorn[standard]==0.30.*" \ redis==5.0.* # Pre-compile bytecode for faster cold start on a read-only rootfs RUN python -m compileall -q /opt/venv # ============================================================================ # Runtime stage: distroless Python 3.11, non-root, no shell # ============================================================================ # gcr.io/distroless/python3-debian12 ships Python 3.11 with NO shell, NO # package manager, and NO setuid binaries. The :nonroot tag pins USER to # uid 65532 / gid 65532. FROM gcr.io/distroless/python3-debian12:nonroot ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 WORKDIR /app # Self-contained venv (its bin/python and site-packages travel together) COPY --from=builder --chown=nonroot:nonroot /opt/venv /opt/venv # Application source (its own layer so source-only changes don't bust dep cache) COPY --chown=nonroot:nonroot app.py favicon.ico /app/ USER nonroot EXPOSE 8000 # Invoking the venv's Python directly makes its site-packages discoverable # automatically (sys.prefix points inside /opt/venv) — no PYTHONPATH needed. ENTRYPOINT ["/opt/venv/bin/python", "-m", "uvicorn"] CMD ["app:app", "--host", "0.0.0.0", "--port", "8000"]