diff --git a/.gitea/workflows/backend-ecr-modal.yaml b/.gitea/workflows/backend-ecr-modal.yaml index 201aa6c..75f809e 100644 --- a/.gitea/workflows/backend-ecr-modal.yaml +++ b/.gitea/workflows/backend-ecr-modal.yaml @@ -5,7 +5,7 @@ name: Backend EC - Modal Deployment on: push: - branches: ['main'] + branches: ['**'] workflow_dispatch: {} permissions: diff --git a/workspace/sprint_1_2/CODEBASE/backend/main.py b/workspace/sprint_1_2/CODEBASE/backend/platform_server.py similarity index 100% rename from workspace/sprint_1_2/CODEBASE/backend/main.py rename to workspace/sprint_1_2/CODEBASE/backend/platform_server.py diff --git a/workspace/sprint_1_2/CODEBASE/deps/implementation/backend_deploy/Dockerfile b/workspace/sprint_1_2/CODEBASE/deps/implementation/backend_deploy/Dockerfile index d671e9d..cdb531e 100644 --- a/workspace/sprint_1_2/CODEBASE/deps/implementation/backend_deploy/Dockerfile +++ b/workspace/sprint_1_2/CODEBASE/deps/implementation/backend_deploy/Dockerfile @@ -65,6 +65,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ g++ \ make \ + libglib2.0-0 \ && rm -rf /var/lib/apt/lists/* # Create virtual environment so we can copy a single tree to runtime @@ -85,19 +86,39 @@ COPY --from=wheelhouse /app/backend /app/backend RUN pip install --no-cache-dir --no-index --find-links=/wheels -r requirements.txt && \ find /opt/venv -type d -name "__pycache__" -exec rm -rf {} + && \ find /opt/venv -type d -name "tests" -exec rm -rf {} + + +# === DISTROLESS PREPARATION === +# 1. Distroless has no shell to run `mkdir` later, so we build our directories here. +RUN mkdir -p /app/logs + +# 2. Extract the critical shared C-libraries that your dynamic CV system needs +# (e.g., libglib) so we can pass them into Distroless manually. +RUN cp /lib/*-linux-gnu/libglib-2.0.so.0 /opt/venv/ # ============================================================================= # Stage 3: Runtime # Minimal image containing only the venv and application code. # ============================================================================= -FROM python:3.12-slim-bookworm AS runtime +# FROM python:3.12-slim-bookworm AS runtime +FROM gcr.io/distroless/cc-debian12 AS runtime WORKDIR /app ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 + +# Copy the exact Python runtime binaries from the builder to prevent path mismatch +COPY --from=builder /usr/local/bin/python3.12 /usr/local/bin/python +COPY --from=builder /opt/venv/libglib-2.0.so.0 /lib/ +COPY --from=builder /usr/local/lib/ /usr/local/lib/ + +# Copy your prepared virtual environment and structures +COPY --from=builder /opt/venv /opt/venv +COPY --from=builder /app/logs /app/logs + + # Step 2: Assign an explicit numeric ID (like 999) when creating the user/group -RUN groupadd -g 999 appgroup && \ - useradd -r -l -u 999 -g appgroup -d /app -s /sbin/nologin appuser +# RUN groupadd -g 999 appgroup && \ +# useradd -r -l -u 999 -g appgroup -d /app -s /sbin/nologin appuser # RUN apt-get update && apt-get install -y --no-install-recommends \ # libgl1 \ @@ -108,30 +129,50 @@ RUN groupadd -g 999 appgroup && \ # libsm6 \ # && rm -rf /var/lib/apt/lists/* -RUN apt-get update && apt-get install -y \ - libglib2.0-0 \ - && rm -rf /var/lib/apt/lists/* - +# RUN apt-get update && apt-get install -y \ +# libglib2.0-0 \ +# && rm -rf /var/lib/apt/lists/* + +# Drop our extracted dynamic system C-libraries into the system runtime path +COPY --from=builder /opt/venv/libglib-2.0.so.0 /lib/x86_64-linux-gnu/libglib-2.0.so.0 + # Step 3: Use the exact matching numeric IDs for --chown -COPY --from=builder --chown=999:999 /opt/venv /opt/venv -ENV PATH=/opt/venv/bin:$PATH +# COPY --from=builder --chown=999:999 /opt/venv /opt/venv # Copy application code -COPY --from=wheelhouse --chown=999:999 /app/backend /app/backend -# Switch to non-root user -# === FIX COMPONENT === -# Pre-create the log directory and hand ownership over to appuser -RUN mkdir -p /app/logs && chown -R 999:999 /app/logs -# ===================== +COPY --from=wheelhouse /app/backend /app/backend -USER appuser +# ENV PATH=/opt/venv/bin:$PATH +ENV PATH=/opt/venv/bin:/usr/local/bin:$PATH +# Copy application code +# COPY --from=wheelhouse --chown=999:999 /app/backend /app/backend # Expose port EXPOSE 8001 -# Health check -HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8001/health')" || exit 1 +# Switch to non-root user +# === FIX COMPONENT === +# Pre-create the log directory and hand ownership over to appuser +# RUN mkdir -p /app/logs && chown -R 999:999 /app/logs +# ===================== +# USER appuser + +# Distroless has built-in nonroot configurations. The user ID 65532 is standard. +# We assign our directories to this default nonroot group/user ID. +COPY --from=builder --chown=65532:65532 /opt/venv /opt/venv +COPY --from=builder --chown=65532:65532 /app/logs /app/logs +USER 65532 + + +# # Health check +# HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ +# CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8001/health')" || exit 1 + + +# NOTE: The HEALTHCHECK block must be deleted or rewritten in native Python code. +# Distroless does not contain a shell (`/bin/sh`), so the `|| exit 1` syntax +# will cause the Docker health check execution framework to completely fail. +# If an automated health check is strictly required, handle it via a native Python orchestration check. # Run the CV inference server CMD ["python", "-m", "backend.cv_inference_server"] \ No newline at end of file diff --git a/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/README.md b/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/README.md index d6e84bd..0251df8 100644 --- a/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/README.md +++ b/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/README.md @@ -97,7 +97,7 @@ export SUPABASE_URL="https://.supabase.co" export SUPABASE_SERVICE_ROLE_KEY="..." export EMBED_QUERY_MOCK=1 # PoC until embedder wired -PYTHONPATH=. uvicorn backend.main:app --host 127.0.0.1 --port 8000 +PYTHONPATH=. uvicornbackend.platform_server:app --host 127.0.0.1 --port 8000 ``` ```bash diff --git a/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/smoke/bff-tools.mjs b/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/smoke/bff-tools.mjs index c0187f7..a38575b 100644 --- a/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/smoke/bff-tools.mjs +++ b/workspace/sprint_1_2/CODEBASE/ml/tests/agent_tools/smoke/bff-tools.mjs @@ -4,7 +4,7 @@ * * Start backend first (from CODEBASE root): * MODAL_MEDGEMMA_ENDPOINT=... EXA_API_KEY=... SUPABASE_URL=... \\ - * PYTHONPATH=. uvicorn backend.main:app --host 127.0.0.1 --port 8000 + * PYTHONPATH=. uvicornbackend.platform_server:app --host 127.0.0.1 --port 8000 * * Usage: * BFF_BASE_URL=http://127.0.0.1:8000 npm run smoke:bff