cinoc / Dockerfile
cinoc-deploy
Déploiement de la vitrine Cinoc
a2907ce
Raw
History Blame Contribute Delete
4.89 kB
# Image **moteur** Cinoc pour un Hugging Face Space (SDK: docker).
#
# ≠ la vitrine lecture seule (deploy/Dockerfile{,.space}) : celle-ci **bake un vrai
# moteur OCR gratuit** (Tesseract 5 + langues fra/lat/eng) pour qu'un visiteur du
# Space public lance un run Tesseract **sans clé ni installation**. Les moteurs
# cloud et les plugins tiers restent *gated* (mode public, fail-closed côté appli).
#
# Contexte de build « racine plate » (Dockerfile / requirements.txt / pyproject.toml
# / cinoc / reports TOUS à la racine) — assemblé par .github/workflows/deploy-space.yml,
# comme Dockerfile.space.
FROM python:3.11-slim
# ── Dépendances système : Tesseract 5 + langues + libs image (Pillow) ──────────
# Les langues sont baquées (pas téléchargées au runtime) : un Space free-tier n'a
# pas d'accès réseau garanti au démarrage, et le déterminisme exige une version de
# binaire figée. ``fra`` est le besoin patrimonial central ; ``lat`` (latin) et
# ``eng`` complètent. Pas de pin de version exacte (Debian point-release rebump
# fréquemment ``5.3.0-2`` → ``+deb12u1`` → casse le build) : la repro repose sur la
# capture de ``tesseract --version`` dans ``RunManifest.system_binaries_lock``.
RUN apt-get update -o Acquire::Retries=3 \
&& apt-get install -y --no-install-recommends -o Acquire::Retries=3 \
tesseract-ocr \
tesseract-ocr-fra \
tesseract-ocr-lat \
tesseract-ocr-eng \
libtiff6 \
libjpeg62-turbo \
libpng16-16 \
libwebp7 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# ── Variables d'exécution ──────────────────────────────────────────────────────
# TESSDATA_PREFIX : emplacement Debian bookworm des modèles Tesseract 5.
ENV TESSDATA_PREFIX=/usr/share/tesseract-ocr/5/tessdata
# OMP_THREAD_LIMIT=1 : OBLIGATOIRE sur free-tier 2 vCPU. Tesseract LSTM (oem 3)
# parallélise via OpenMP ; non borné sur un CPU partagé il **deadlock** (incident
# documenté côté Picarones, 2026-05-16) — l'OCR gèle et chaque document timeoute.
# Mono-thread par appel = plus rapide ET déterministe ici.
ENV OMP_THREAD_LIMIT=1
# Mode public (verrou *fail-closed*) **non forcé** : par défaut l'instance exécute
# ses moteurs (cloud compris) avec la clé de l'opérateur — pas de 403. Qui expose
# un Space **public** et veut protéger sa clé d'un visiteur pose lui-même
# CINOC_PUBLIC_MODE=true (alors seul le socle gratuit tesseract s'exécute).
ENV PYTHONUNBUFFERED=1
# ── Smoke-test du binaire au BUILD (fail-fast) ─────────────────────────────────
# Un Tesseract cassé OU figé doit casser le BUILD (le Space garde l'image
# précédente fonctionnelle), pas déployer une image qui gèle en silence :
# (a) le binaire charge ses libs et expose la langue ``fra`` (sinon build refusé) ;
# (b) une reconnaissance réelle sur une image générée se TERMINE sous 30 s — un
# timeout (rc 124) = deadlock OpenMP / libs incohérentes → build refusé.
RUN set -eu; \
timeout 30 tesseract --version; \
timeout 30 tesseract --list-langs 2>&1 | grep -qx fra; \
printf 'P1\n16 16\n' > /tmp/smoke.pbm; \
i=0; while [ "$i" -lt 16 ]; do \
printf '1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n' >> /tmp/smoke.pbm; \
i=$((i + 1)); \
done; \
rc=0; \
timeout 30 tesseract /tmp/smoke.pbm - -l fra --psm 6 >/dev/null 2>&1 || rc=$?; \
rm -f /tmp/smoke.pbm; \
if [ "$rc" = 124 ]; then \
echo "FATAL: tesseract a gelé (timeout) — build refusé, libs incohérentes." >&2; \
exit 1; \
fi
# ── Utilisateur non-root (sécurité d'un service exposé) ────────────────────────
RUN useradd --create-home --uid 1000 cinoc
WORKDIR /home/cinoc/app
# ── Dépendances Python d'abord (cache de couche) ───────────────────────────────
# requirements.txt fige le cœur + l'extra [serve] + pytesseract (wrapper du binaire).
COPY requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# ── Code + paquet (sans deps : tout est déjà figé ci-dessus) ───────────────────
COPY pyproject.toml README.md ./
COPY cinoc ./cinoc
RUN pip install --no-cache-dir --no-deps .
# ── Rapports bakés (lecture seule) — dossier toujours présent ──────────────────
COPY reports ./reports
ENV CINOC_REPORTS_DIR=/home/cinoc/app/reports
USER cinoc
EXPOSE 7860
# 0.0.0.0 attendu en conteneur (le réseau est géré par la plateforme).
CMD ["cinoc", "serve", "--host", "0.0.0.0", "--port", "7860"]