File size: 3,750 Bytes
01211a2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9203c28
01211a2
 
7f6dc6d
4871d44
 
 
 
 
 
 
7f6dc6d
9203c28
 
 
 
 
 
01211a2
 
 
 
 
9452c00
 
 
01211a2
 
 
9452c00
 
01211a2
9452c00
01211a2
9452c00
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# ────────────────────────────────────────────────────────────────────────────
# GuichetOI ML β€” production Docker image
# ────────────────────────────────────────────────────────────────────────────
# β€’ Tesseract with the French language pack is a runtime requirement.
# β€’ Model weights are baked in (under ~2 GB total) so the image is a
#   single self-contained artifact β€” simplest CI/CD and Kubernetes rollout.
#   To slim the image, drop the COPY for models/ and mount /app/models as
#   a volume at runtime instead.
# β€’ Uses one worker β€” the ML pipeline keeps ~1.2 GB of weights resident
#   in RAM; multiple workers would multiply the memory footprint. Scale
#   horizontally with container replicas, not workers.
# ────────────────────────────────────────────────────────────────────────────
FROM python:3.12-slim AS runtime

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

# System deps:
#   tesseract-ocr + tesseract-ocr-fra : French OCR for the inference pipeline
#   libgl1 + libglib2.0-0             : runtime for opencv-python (used by
#                                       ocr_rasterise.py)
#   curl                              : HEALTHCHECK probe
RUN apt-get update && apt-get install -y --no-install-recommends \
        tesseract-ocr \
        tesseract-ocr-fra \
        libgl1 \
        libglib2.0-0 \
        curl \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install Python deps first for cache-friendly rebuilds
COPY requirements.txt pyproject.toml ./
RUN pip install --upgrade pip && pip install -r requirements.txt

# Application code + assets.
# The Space uses public HF Hub model repos by default so the container can
# bootstrap without a private-model secret. Override these env vars only if
# you want to point at different local paths or private repos.
ENV GUICHETOI_CLASSIFIER_DIR="AzizMiladi/guichetoi-classifier" \
    GUICHETOI_EXTRACTOR_DIR="AzizMiladi/guichetoi-extractor"

# Models are resolved by guichetoi.inference at startup. To bake models into
# the image instead (Render-style), re-add: COPY models/ ./models/
COPY src/                              ./src/
COPY assets/cms_template.xlsx          ./assets/cms_template.xlsx
COPY assets/label_mappings.json        ./assets/label_mappings.json

# Install the package so `uvicorn guichetoi.api.main:app` resolves.
RUN pip install --no-deps -e .

# Default CORS = open; override in compose/Helm/k8s when calling Angular
# directly. Leave unset when only Spring Boot calls this service.
ENV GUICHETOI_CORS_ORIGINS="*"

# Render injects $PORT (typically 10000); locally it defaults to 8000.
# Use shell form so $PORT actually expands at container start.
ENV PORT=8000
EXPOSE 8000

# start-period covers the ~30 s model load. Spring Boot's readiness probe
# can call the same endpoint with the same allowance. Render's own health
# checks use the path configured in render.yaml β€” same URL works for both.
HEALTHCHECK --interval=30s --timeout=10s --start-period=120s --retries=3 \
    CMD curl -fsS http://127.0.0.1:${PORT}/health | grep -q '"pipeline_loaded": *true' || exit 1

# Shell form (no JSON array) so $PORT expands at runtime.
CMD uvicorn guichetoi.api.main:app --host 0.0.0.0 --port ${PORT} --workers 1