Ctrl K
ComunidadGuías…

deploy/docker/Dockerfile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# syntax=docker/dockerfile:1.7

# --- builder ---
FROM python:3.11-slim AS builder

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PIP_NO_CACHE_DIR=1

WORKDIR /build

RUN apt-get update && apt-get install -y --no-install-recommends \
        build-essential curl ca-certificates \
    && rm -rf /var/lib/apt/lists/*

RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \
    cp /root/.local/bin/uv /usr/local/bin/uv

# Deterministic, dependencies-ONLY install pinned from uv.lock (NOT pyproject
# ranges) and EXCLUDING the project itself (--no-emit-project). Two payoffs:
#   1. reproducible — the resolved dep set is fixed by the lock, so the same
#      commit always yields the same site-packages bytes;
#   2. cache-stable — this ~1GB layer's inputs are only pyproject.toml + uv.lock,
#      so a code-only change does NOT rebuild it and cluster nodes reuse the
#      already-pulled layer (no slow multi-minute re-pull → no helm hook timeout).
# The project code itself is NOT installed here; it ships as /app/src and runs
# via PYTHONPATH in the runtime stage (a separate, tiny layer).
COPY pyproject.toml uv.lock README.md ./
RUN uv export --frozen --no-dev --no-emit-project -o /tmp/requirements.txt && \
    uv pip install --system --no-cache -r /tmp/requirements.txt

# --- runtime: distroless ---
# Pinned to a known-good digest. Bump via Renovate (PR + Trivy gate).
FROM gcr.io/distroless/python3-debian12:nonroot AS runtime

WORKDIR /app

# Dependencies (stable layer — changes only when uv.lock changes).
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=builder /usr/local/bin/alembic /usr/local/bin/alembic

# distroless `python3` lives at /usr/bin/python3.11 with sys.path NOT including
# our paths by default. Put the project source (/app/src) FIRST so `ai_api` is
# imported from the small code layer, then the deps in site-packages. Everything
# is invoked as `python3 -m …` (uvicorn / alembic / ai_api.cli.*), so no reliance
# on console-script shebangs.
ENV PYTHONPATH=/app/src:/usr/local/lib/python3.11/site-packages \
    PATH=/usr/local/bin:$PATH \
    PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

# Project code — its own small layer (changes on every code edit, but it's tiny).
COPY src/ ./src/
COPY alembic/ ./alembic/
COPY alembic.ini ./
COPY deploy/docker/healthcheck.py /app/healthcheck.py

USER nonroot

EXPOSE 8000
HEALTHCHECK --interval=10s --timeout=5s --retries=5 \
    CMD ["python3", "/app/healthcheck.py"]

ENTRYPOINT ["python3"]
CMD ["-m", "uvicorn", "ai_api.main:app", "--host", "0.0.0.0", "--port", "8000"]