# ============================================================================= # Dockerfile — Déploiement sur Hugging Face Spaces (type "Docker") # ============================================================================= # # QU'EST-CE QU'UN DOCKERFILE ? # La recette de construction d'une IMAGE Docker : un environnement complet # et figé (OS + Python + dépendances + notre code) qui s'exécute à # l'identique partout. Si le conteneur tourne sur ma machine, il tournera # exactement pareil sur Spaces — fini le "ça marche chez moi". # # POURQUOI DOCKER ICI ? # Hugging Face Spaces propose 4 types de SDK : Gradio, Streamlit, statique # et Docker. Seul le type Docker permet de lancer un serveur arbitraire — # donc notre API FastAPI. Contrainte de Spaces : l'application DOIT # écouter sur le port 7860. # # OÙ EST LE MODÈLE ? # PAS dans l'image (il pèse 270 Mo et changerait à chaque ré-entraînement). # Il est sur le HF Hub ; l'API le télécharge au démarrage grâce à la # variable d'environnement MODEL_ID (à régler dans Settings > Variables # du Space, ex : MODEL_ID=rima/avissense-distilcamembert). # # TESTER EN LOCAL (optionnel, nécessite Docker Desktop) : # docker build -t avissense . # docker run -p 7860:7860 -e MODEL_ID=rima/avissense-distilcamembert avissense # -> http://localhost:7860/docs # ============================================================================= # Image de départ : Python 3.11 officiel, variante "slim" = sans les outils # superflus -> image finale plus légère et plus rapide à déployer. FROM python:3.11-slim # Tous les chemins relatifs des instructions suivantes partent de /app # (le dossier est créé automatiquement s'il n'existe pas). WORKDIR /app # ── ASTUCE DE CACHE DOCKER ─────────────────────────────────────────────────── # Docker construit l'image par COUCHES et met chaque couche en cache : une # couche n'est reconstruite que si ce qu'elle copie/exécute a changé. # En copiant requirements.txt SEUL avant le reste du code, l'installation # des dépendances (l'étape la plus longue, ~5 min : torch est gros) reste en # cache tant que requirements.txt ne change pas. Modifier api/main.py ne # redéclenche PAS le pip install -> rebuilds en quelques secondes. COPY requirements.txt . # --no-cache-dir : pip ne garde pas les archives téléchargées -> image # plus petite (le cache pip ne servirait à rien dans une image figée). RUN pip install --no-cache-dir -r requirements.txt # Maintenant seulement, copier tout le code du projet (api/, scripts/...). # Le .gitignore n'est pas utilisé par Docker, mais les poids du modèle ne # sont de toute façon pas dans le repo (ils sont sur le Hub). COPY . . # Spaces exécute le conteneur avec un utilisateur NON-root qui n'a pas le # droit d'écrire n'importe où. Or transformers télécharge le modèle dans un # cache (par défaut ~/.cache/huggingface, non accessible en écriture ici). # On redirige ce cache vers /tmp, accessible en écriture à tout le monde. ENV HF_HOME=/tmp/hf_cache # Documente le port utilisé (Spaces s'attend à 7860). EXPOSE 7860 # La commande lancée au démarrage du conteneur : # uvicorn api.main:app -> le serveur ASGI qui exécute notre app FastAPI # --host 0.0.0.0 -> écoute sur TOUTES les interfaces réseau # (avec 127.0.0.1, seul l'intérieur du conteneur # pourrait se connecter : l'API serait invisible) # --port 7860 -> le port imposé par Hugging Face Spaces CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "7860"]