Docker et IA : Déployer un Modèle du Prototype à la Production
Votre modèle IA fonctionne parfaitement sur l’ordinateur de votre data scientist. Puis vient le moment fatidique du déploiement : dépendances manquantes, versions de bibliothèques incompatibles, “ça marchait sur ma machine”. Cette situation, que 73 % des équipes data ont vécu selon le rapport State of ML 2024 de Weights & Biases, a un remède connu et éprouvé : Docker. Conteneuriser un modèle IA n’est plus une compétence réservée aux DevOps — c’est une étape incontournable du cycle de vie de tout projet IA en production.
Pourquoi conteneuriser un modèle IA ?
Un modèle de machine learning n’est jamais seul : il dépend d’une version précise de Python, de PyTorch ou TensorFlow, de CUDA pour le GPU, de dizaines de bibliothèques avec leurs propres sous-dépendances. Sans isolation, ce “dependency hell” rend le déploiement cauchemardesque et la reproductibilité impossible.
Docker résout ce problème en encapsulant votre modèle et tout son environnement dans une image portable, qui s’exécute de manière identique sur votre laptop, un serveur cloud, ou un Raspberry Pi (avec les bons paramètres).
Avantages concrets pour une PME :
- Déploiement reproductible en quelques minutes
- Rollback instantané en cas de problème (revenir à l’image précédente)
- Scalabilité horizontale facile (Kubernetes, Docker Swarm)
- Isolation des dépendances entre projets IA
- CI/CD automatisable
Dockerfile multi-stage pour un modèle Python/FastAPI
L’image Docker d’un modèle IA peut facilement dépasser 10 Go si elle est mal construite (PyTorch pèse 3+ Go). La stratégie multi-stage permet de séparer l’environnement de build de l’image de production finale.
Prenons un exemple concret : exposer un modèle de classification de texte via une API FastAPI.
# ===== STAGE 1 : Build =====
FROM python:3.11-slim AS builder
WORKDIR /app
# Installer les dépendances de build
RUN apt-get update && apt-get install -y
gcc
g++
&& rm -rf /var/lib/apt/lists/*
# Copier et installer les dépendances (couche mise en cache)
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# ===== STAGE 2 : Production =====
FROM python:3.11-slim AS production
WORKDIR /app
# Copier uniquement les packages installés depuis le builder
COPY /root/.local /root/.local
# Copier le code de l'application
COPY app/ ./app/
COPY models/ ./models/
# Variables d'environnement
ENV PYTHONPATH=/app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PATH=/root/.local/bin:$PATH
# Utilisateur non-root pour la sécurité
RUN adduser --disabled-password --gecos '' appuser
USER appuser
EXPOSE 8000
# Health check intégré
HEALTHCHECK
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"] L’API FastAPI correspondante :
# app/main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from transformers import pipeline
import logging
logger = logging.getLogger(__name__)
app = FastAPI(title="Modèle Classification Texte", version="1.0.0")
# Charger le modèle au démarrage (une seule fois)
classifier = None
@app.on_event("startup")
async def load_model():
global classifier
logger.info("Chargement du modèle...")
classifier = pipeline(
"text-classification",
model="./models/mon-modele-finetune",
device=-1 # CPU (-1) ou GPU (0)
)
logger.info("Modèle chargé avec succès")
@app.get("/health")
async def health():
return {"status": "ok", "model_loaded": classifier is not None}
class TextRequest(BaseModel):
text: str
class PredictionResponse(BaseModel):
label: str
score: float
@app.post("/predict", response_model=PredictionResponse)
async def predict(request: TextRequest):
if classifier is None:
raise HTTPException(503, "Modèle non disponible")
result = classifier(request.text)[0]
return PredictionResponse(label=result["label"], score=result["score"]) Docker Compose : orchestrer le stack complet
En production, votre modèle IA ne tourne jamais seul. Il a besoin d’une base de données, d’un cache Redis pour les requêtes fréquentes, d’un reverse proxy. Docker Compose orchestre tout cela.
# docker-compose.yml
version: '3.8'
services:
# API du modèle IA
model-api:
build:
context: .
dockerfile: Dockerfile
target: production
image: mon-modele-ia:1.0.0
restart: unless-stopped
environment:
- MODEL_PATH=/app/models/mon-modele
- REDIS_URL=redis://redis:6379
- LOG_LEVEL=INFO
volumes:
# Monter les modèles depuis l'hôte (évite de les inclure dans l'image)
- ./models:/app/models:ro
- ./logs:/app/logs
ports:
- "8000:8000"
depends_on:
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# Limites de ressources
deploy:
resources:
limits:
cpus: '2.0'
memory: 4G
reservations:
memory: 2G
# Cache pour les prédictions fréquentes
redis:
image: redis:7-alpine
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- redis-data:/data
# Reverse proxy (optionnel en dev, essentiel en prod)
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- model-api
volumes:
redis-data: Support GPU : YOLO comme exemple concret
Les modèles de vision par ordinateur comme YOLO nécessitent un GPU pour des performances acceptables. Voici comment configurer Docker avec support GPU.
Prérequis hôte : installer NVIDIA Container Toolkit.
# Installation NVIDIA Container Toolkit (Ubuntu)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor
-o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list |
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' |
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker Dockerfile pour YOLO avec GPU :
FROM pytorch/pytorch:2.2.0-cuda12.1-cudnn8-runtime
WORKDIR /app
RUN pip install --no-cache-dir
ultralytics==8.1.0
fastapi==0.110.0
uvicorn[standard]==0.27.0
python-multipart==0.0.9
COPY models/yolo11n.pt ./models/
COPY app/ ./app/
EXPOSE 8001
CMD ["uvicorn", "app.yolo_api:app", "--host", "0.0.0.0", "--port", "8001"] docker-compose avec GPU :
services:
yolo-api:
build: .
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1 # ou "all" pour tous les GPU
capabilities: [gpu]
environment:
- CUDA_VISIBLE_DEVICES=0
volumes:
- ./models:/app/models:ro API de détection d’objets :
# app/yolo_api.py
from fastapi import FastAPI, UploadFile
from ultralytics import YOLO
import io
from PIL import Image
app = FastAPI()
model = YOLO("./models/yolo11n.pt")
@app.post("/detect")
async def detect(file: UploadFile):
image_data = await file.read()
image = Image.open(io.BytesIO(image_data))
results = model(image, conf=0.5)
detections = []
for result in results:
for box in result.boxes:
detections.append({
"class": result.names[int(box.cls)],
"confidence": float(box.conf),
"bbox": box.xyxy[0].tolist()
})
return {"detections": detections, "count": len(detections)} Gestion des volumes et des modèles
Un anti-pattern courant : inclure les fichiers de modèle (qui pèsent souvent plusieurs Go) dans l’image Docker. Cela rend l’image lourde et le push/pull lent.
Bonne pratique : monter les modèles en volume
# Les modèles sont sur l'hôte ou dans un stockage partagé
volumes:
- /data/models:/app/models:ro # Read-only pour la sécurité
- /data/logs:/app/logs # Read-write pour les logs Pour les environnements cloud (AWS EFS, Azure Files, GCP Filestore) :
volumes:
models-efs:
driver: local
driver_opts:
type: nfs
o: addr=fs-xxxxx.efs.eu-west-3.amazonaws.com,nfsvers=4.1,rsize=1048576
device: ":/" CI/CD pour vos modèles IA
Un pipeline de déploiement continu pour un modèle IA doit inclure des étapes spécifiques :
# .github/workflows/deploy-model.yml
name: Build and Deploy Model API
on:
push:
branches: [main]
paths: ['app/**', 'models/**', 'Dockerfile', 'requirements.txt']
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run model tests
run: |
pip install -r requirements-test.txt
pytest tests/ -v --tb=short
build-and-push:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build -t mon-registre/model-api:${{ github.sha }} .
docker tag mon-registre/model-api:${{ github.sha }} mon-registre/model-api:latest
- name: Push to registry
run: docker push mon-registre/model-api:${{ github.sha }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Deploy to production
run: |
ssh ${{ secrets.PROD_HOST }} "
docker pull mon-registre/model-api:${{ github.sha }}
docker-compose up -d --no-deps model-api
" Bonnes pratiques de sécurité
Ne jamais faire :
- Inclure des clés API ou credentials dans l’image Docker
- Faire tourner le conteneur en root (utilisez
USER appuser) - Exposer directement le port du modèle sans reverse proxy
Toujours faire :
# Secrets via variables d'environnement (jamais en dur)
ENV API_KEY=${API_KEY}
# Utilisateur non-root
RUN addgroup --system appgroup && adduser --system --group appuser
USER appuser
# Image minimale
FROM python:3.11-slim # pas python:3.11 (full) # Lancer avec .env (jamais commité)
docker run --env-file .env mon-modele-ia:latest Conclusion
Docker a transformé le déploiement de modèles IA d’une opération risquée et imprévisible en un processus reproductible et automatisable. Les patterns présentés ici — multi-stage build, Compose avec health checks, support GPU, volumes pour les modèles — couvrent la grande majorité des cas de déploiement en PME.
Le passage du prototype à la production est souvent l’étape qui fait échouer les projets IA. Investir dans une bonne infrastructure Docker dès le début du projet, c’est s’assurer que la valeur créée par votre modèle arrive réellement à vos utilisateurs.
Votre équipe a un modèle IA qui tourne en local et vous souhaitez le déployer en production ? Brio Novia accompagne les PME dans la mise en production de leurs modèles IA, de la conteneurisation au monitoring en production. Contactez-nous à contact@brio-novia.eu pour en discuter.