Procédure de Déploiement
Ce document décrit la procédure complète de déploiement de la solution FirstBreath, de l'installation du serveur à la mise en production.
1. PaaS — Dokploy
Nous utilisons Dokploy, un PaaS open-source auto-hébergé, pour gérer les déploiements sur notre VPS OVH.
Pourquoi Dokploy ?
| Critère | Avantage |
|---|---|
| Open-source | Pas de coût de licence, contrôle total |
| Git integration | Déploiement automatique depuis un push Git |
| Docker natif | Chaque app pointe vers un docker-compose.dokploy.yml |
| Traefik intégré | Reverse proxy, TLS, load balancing automatiques |
| Interface web | Gestion visuelle des applications, logs, variables d'environnement |
Structure des applications
| Application | Dépôt | Fichier Compose | Port(s) |
|---|---|---|---|
control-hub-back | Control-Hub-Back | docker-compose.dokploy.yml | 8080 (API), 8080 (WS) |
firstbreath-vision | firstbreath-vision | docker-compose.dokploy.yml | 4000-4002 (Prometheus) |
platform-docs | FirstBreath-Platform | apps/docs/Dockerfile | 80 (Nginx) |
firstbreath-showcase | Firstbreath Showcase | docker-compose.yml | 3000 |
2. Conteneurisation — Docker
Stratégie de build multi-étapes
Tous les Dockerfiles utilisent un build multi-étapes pour minimiser la taille des images et améliorer la sécurité.
Control-Hub-Back (API / WebSocket)
Base (node:20-alpine) → Deps (yarn install) → Build (yarn build) → Production
- Image de base :
node:20.12.2-alpine3.18(version fixée) - Utilisateur non-root (
nodejs:1001) - Seuls les artefacts compilés (
/app/build) etnode_modulessont copiés en production
Firstbreath Showcase (Dashboard)
Deps (pnpm install) → Builder (prisma generate + next build) → Runner
- Image de base :
node:22-alpine - Standalone output de Next.js pour une image minimale
- Migration Prisma séparée via un service
migrate(exécuté avantweb) - Utilisateur non-root (
nextjs)
Control-Hub Frontend (my-app)
Deps (pnpm install) → Builder (next build) → Runner
- Standalone output Next.js
- Utilisateur non-root (
nextjs:1001)
Vision — Camera Manager
- Image de base :
ghcr.io/firstbreath/opencv-cuda:latest(image custom) - Image custom compilée avec CUDA 12.4, cuDNN, FFmpeg CUDA, OpenCV 4.10 CUDA
- GPU NVIDIA requis (driver capabilities)
Vision — Batch Inference
- Image de base :
ultralytics/ultralytics:latest - Modèle YOLO embarqué (
model.pt) - GPU NVIDIA requis
Vision — Redis Worker
Builder (pip install) → Runtime (python:3.11-slim)
- Build multi-étapes pour séparer les dépendances
- Utilisateur non-root (
appuser) - Healthcheck intégré
Documentation (Docusaurus)
Builder (npm ci + npm run build) → Nginx Alpine
- Build statique servi par Nginx
- Configuration SPA (
try_files)
Image de base custom : OpenCV CUDA
L'image ghcr.io/firstbreath/opencv-cuda est construite à partir de nvidia/cuda:12.4.1-cudnn-devel-ubuntu22.04 et compile :
- FFmpeg 6.1 avec support CUDA (nvenc, cuvid, npp)
- OpenCV 4.10 avec support CUDA, cuDNN, FFmpeg
- Python 3.11 avec NumPy
Cette image est stockée sur GitHub Container Registry et partagée entre les services Vision.
3. Orchestration — Docker Compose
Environnement de production (docker-compose.dokploy.yml)
Stack Control-Hub-Back
| Service | Image | Healthcheck | Restart |
|---|---|---|---|
mysql | mysql:8 | mysqladmin ping | always |
redis | redis:alpine | redis-cli -a $PASS ping | unless-stopped |
api (×2) | Build local | — | unless-stopped |
websocket | Build local | — | unless-stopped |
cloudbeaver | dbeaver/cloudbeaver | — | unless-stopped |
Points clés :
- L'API tourne en 2 replicas avec load balancing Traefik
- Redis configuré avec
maxmemory 256mbet politiqueallkeys-lru - MySQL avec
wait_timeoutà 1 an pour les connexions longues - Labels Traefik pour le routage HTTPS (
api.firstbreath.fr) - Service
init-permissionspour les volumes de fichiers uploadés
Stack Vision
| Service | Image | GPU | Healthcheck |
|---|---|---|---|
camera-manager | Build (opencv-cuda) | 1× NVIDIA | pgrep -f src/manager.py |
batch-inference | Build (ultralytics) | 1× NVIDIA | pgrep -f inference_service |
redis-worker | Build (python-slim) | — | pgrep -f python worker.py |
Points clés :
- Communication inter-services via le réseau
monitor-net - Accès à la base MySQL du Control-Hub sans exposition publique
- Réservation GPU obligatoire (
nvidiadriver, capabilities[gpu]) - Cache TensorRT persisté via un volume Docker (
trt-engine-cache)
Environnement de développement (docker-compose.yml)
L'environnement de développement local inclut des services supplémentaires :
- RTSP Server (MediaMTX) : simulation de flux caméra avec vidéos de test
- RTSPtoWeb : transcoding RTSP → WebRTC/HLS pour le navigateur
- Prometheus + Grafana : monitoring local identique à la production
4. Routage et domaines
Le routage est géré par Traefik via des labels Docker.
| Domaine | Service | Entrypoint | TLS |
|---|---|---|---|
api.firstbreath.fr | API REST (×2) | websecure | Let's Encrypt |
api.firstbreath.fr/socket.io | WebSocket | websecure (priorité 100) | Let's Encrypt |
db.firstbreath.fr | CloudBeaver | websecure | Let's Encrypt |
sonar.firstbreath.fr | SonarQube | websecure | Let's Encrypt |
Redirection HTTP → HTTPS : middleware redirect-to-https@file.
5. Procédure de déploiement pas à pas
Premier déploiement (nouveau serveur)
- Installer Dokploy sur le VPS (script officiel)
- Configurer les applications dans l'interface Dokploy :
- Ajouter le dépôt Git
- Pointer vers le
docker-compose.dokploy.yml - Configurer les variables d'environnement
- Configurer les domaines et certificats TLS
- Créer les réseaux Docker :
docker network create dokploy-network
docker network create monitor-net - Déployer via Dokploy (bouton Deploy ou push Git)
Déploiement continu (mise à jour)
Vérification post-déploiement
- Tous les conteneurs sont
healthy(docker compose ps) - L'API répond sur
https://api.firstbreath.fr - Les WebSockets fonctionnent (
/socket.io) - Les dashboards Grafana montrent les métriques
- Les logs ne contiennent pas d'erreurs (
docker compose logs -f)