Développement

Comment déployer un modèle GPT privé avec docker et maxmilli pour garder les données clients hors du cloud public

Comment déployer un modèle GPT privé avec docker et maxmilli pour garder les données clients hors du cloud public

Garder les données clients hors des clouds publics tout en profitant de modèles de type GPT est devenu une exigence pour beaucoup d’équipes produit et d’agences. Récemment, j’ai entrepris de monter une stack locale pour héberger un modèle privé en production : Docker pour l’isolation et la reproductibilité, et maxmilli comme moteur d’inférence (vous pouvez remplacer par un autre serveur d’inférence si vous préférez). Dans cet article je partage pas à pas mon approche, mes choix techniques et les pièges que j’ai rencontrés — de la préparation des modèles au déploiement sécurisé.

Pourquoi déployer en local ?

Pour moi, les raisons sont claires : confidentialité des données, latence maîtrisée, coût prévisible et indépendance vis-à-vis d’un fournisseur cloud. Héberger le modèle sur une machine contrôlée permet d’appliquer des politiques de rétention, d’audit et de chiffrement strictes, indispensables pour des données sensibles (données clients, dossiers médicaux, IPs propriétaires, etc.).

Choix du modèle et format

Avant tout, il faut choisir le modèle adapté à votre cas d’usage. Pour des besoins conversationnels, les familles Llama, MPT ou même des modèles conçus pour l’on-premise sont pertinentes. J’ai privilégié un modèle de taille moyenne (7B-13B) pour un bon compromis entre qualité et coûts d’infrastructure.

Important : préférez un format optimisé pour l’inférence locale (ex. GGUF, quantized GGML, ONNX selon l’inférence engine). La quantification (8-bit, 4-bit) réduit drastiquement la RAM/GPU nécessaire et permet de déployer sur des serveurs modestes.

Architecture cible

Voici l’architecture que j’ai mise en place :

  • Serveur physique ou VM (GPU recommandé si latence/qualité importantes)
  • Docker + docker-compose pour isoler le service
  • maxmilli (conteneur d’inférence) exposant une API HTTP/REST locale
  • Reverse proxy (nginx ou Caddy) pour TLS et contrôle d’accès
  • Réseau interne privé, firewall, et authentification par tokens
  • Préparer l’environnement et le modèle

    Sur la machine hôte, j’ai prévu :

  • Stockage SSD rapide (les modèles quantifiés se chargent plus vite)
  • Un GPU NVIDIA (optionnel) avec drivers et CUDA, si vous voulez de la performance
  • Un utilisateur système dédié pour exécuter Docker et limiter les droits
  • Ensuite, j’ai téléchargé le modèle sur une machine sécurisée. Si le modèle est fourni sous licence, vérifiez bien les conditions d’utilisation. Pour la quantification, j’ai utilisé des outils compatibles ggml/gguf ; la procédure dépend du modèle. L’idée : obtenir un fichier model.gguf (ou équivalent) prêt à être utilisé par le moteur d’inférence.

    Créer l’image Docker

    Je préfère ne pas builder l’image complète à la main si un conteneur officiel existe, mais j’ai travaillé avec un Dockerfile minimal pour intégrer maxmilli et monter le modèle via un volume. Exemple simplifié :

    <!-- Dockerfile -->

    <pre>FROM ubuntu:22.04RUN apt-get update && apt-get install -y ca-certificates curl# installer les dépendances nécessaires pour maxmilli# ajouter l'utilisateur non-rootRUN useradd -m appuserUSER appuserWORKDIR /home/appuser# si maxmilli propose une binaire ou script, le copier iciCOPY start-server.sh /home/appuser/RUN chmod +x /home/appuser/start-server.shCMD ["/home/appuser/start-server.sh"]</pre>

    Mon script start-server.sh lance le moteur d’inférence en pointant vers /models/model.gguf monté en volume.

    docker-compose : orchestration simple

    Pour moi, docker-compose est suffisant pour démarrer et maintenir le service en local. Exemple :

    <pre>version: "3.8"services: maxmilli: image: maxmilli/maxmilli:latest # exemple, adaptez selon l'image réelle restart: unless-stopped volumes: - ./models:/models:ro environment: - MODEL_PATH=/models/model.gguf - AUTH_TOKEN=change_me_long_random_token ports: - "127.0.0.1:5000:5000" # bind local seulement shm_size: "1g" deploy: resources: reservations: devices: - capabilities: [gpu]</pre>

    Je recommande de binder l’API sur 127.0.0.1 et de mettre en place un reverse-proxy en frontal si vous devez exposer des endpoints sécurisés. Pour le prod, j’utilise nginx ou Caddy pour gérer TLS et rate-limiting.

    Sécuriser l’accès

    Quelques mesures que j’applique systématiquement :

  • Binding local + reverse proxy qui impose TLS (Let's Encrypt ou certificat interne).
  • Authentification par token ou JWT pour tout appel à l’API.
  • Firewall (ufw/iptables) pour n’ouvrir que les ports nécessaires.
  • Audit des logs et rotation. Ne journalisez pas les prompts sensibles en clair.
  • Chiffrement au repos : disque chiffré si le serveur héberge des données sensibles.
  • Mises à jour régulières des images Docker et du système hôte.
  • Conserver les données hors du cloud public

    C’est le cœur du sujet : je m’assure que :

  • Les requêtes et les données clients ne quittent jamais le réseau interne. Pas d’appels vers des APIs externes sans contrôle explicite.
  • Les dépendances et modèles sont téléchargés préalablement depuis une machine sûre et importés sur le serveur — pas de téléchargement dynamique en production.
  • Les sauvegardes chiffrées sont stockées dans un emplacement contrôlé (NAS chiffré, SFTP interne), jamais sur un bucket public.
  • Optimisation et performance

    Quelques leviers pour améliorer les temps de réponse :

  • Quantification du modèle (4/8 bits) pour réduire la mémoire et accélérer l’inférence.
  • Utiliser la batch inference si vous traitez des flux de requêtes.
  • Cache des embeddings ou réponses fréquemment sollicitées.
  • Surveiller l’usage GPU/CPU et ajuster les ressources Docker (cpus, mémoire, shm_size).
  • Tests et validation

    Avant toute mise en production, j’exécute :

  • Tests de charge pour valider la latence et la consommation mémoire.
  • Tests de sécurité (scanning d’images, analyses vulnérabilités).
  • Tests d’intégrité fonctionnelle : vérification que le modèle répond sans fuite de données externes.
  • Maintenance et gouvernance

    Quelques règles que j’ai mises en place pour maintenir le service :

  • Politique de rotation des tokens et des certificats.
  • Processus de mise à jour des modèles (versioning et rollback).
  • Documentation interne sur la configuration et les procédures d’incident.
  • Bonnes pratiques opérationnelles

    En pratique, j’ai appris à :

  • Isoler les environnements (dev/test/prod) pour éviter les erreurs de configuration.
  • Automatiser les déploiements de modèles via pipelines CI/CD sécurisés (sans exposer les secrets).
  • Limiter la conservation des données utilisateurs dans les logs et la mémoire du processus.
  • Si vous démarrez, commencez petit : un serveur local, un modèle quantifié, un reverse proxy avec TLS et un token d’authentification. Ensuite, instrumentez, mesurez, et adaptez la taille du modèle ou l’architecture en fonction des besoins réels. Si vous voulez, je peux fournir un exemple concret de docker-compose complet adapté à votre infrastructure (GPU vs CPU), ou vous aider à choisir le modèle et la stratégie de quantification qui conviennent à votre cas d’usage.

    Vous devriez également consulter les actualités suivante :