Cours NestJS · Module 9: Déploiement et infrastructure

PROJET : Déploiement complet d'une application NestJS en production

4 min de lecture
Dans cette leçon2

Légat ! Ton application tourne sur ton ordinateur portable, mais le consul Caesar.js pose les questions qui surgissent à chaque vrai déploiement : que se passe-t-il quand le serveur s'éteint à trois heures du matin ? Qui remarquera que la base ralentit ? Comment sais-tu que la sauvegarde d'hier peut être restaurée ? Le consul te confie le plus grand défi : le déploiement complet de la légion romaine en production. C'est le véritable test des compétences que tu as acquises pendant notre campagne NestJS.

Spécification du projet

Ta mission consiste à créer un système de déploiement complet pour l'application Legionary Legion API. Chaque partie s'appuie sur les leçons de ce module et des précédents, alors avant de commencer, reviens-y comme à des cartes d'état-major. Les heures indiquées sont une durée de travail approximative.

1. Infrastructure (4-5 heures)

  • Configuration Docker et Docker Compose
  • Mise en place des charts Kubernetes/Helm
  • Configuration du pipeline CI/CD
  • Surveillance et journalisation

Commence par une image construite en multi-stage build et un fichier Compose qui lance l'application avec MongoDB et Redis. Dans Kubernetes, décris les réplicas, la stratégie de rolling update et les sondes readiness et liveness. Le pipeline doit lancer les tests, construire l'image et ne la déployer qu'une fois les tests au vert.

2. Sécurité (2-3 heures)

  • Implémentation SSL/TLS
  • En-têtes de sécurité et rate limiting
  • Gestion des secrets
  • Analyse des vulnérabilités

Tu connais déjà HTTPS, les en-têtes de Helmet et les limites du throttler. Garde les secrets hors du dépôt et de l'image, et fais en sorte que l'application refuse de démarrer quand l'un d'eux manque. Ajoute au pipeline un scanner de vulnérabilités, par ex. Trivy, pour qu'une image présentant une faille critique n'arrive jamais en production.

3. Performances (2-3 heures)

  • Load balancing et auto-scaling
  • Stratégie de cache
  • Optimisation de la base de données
  • Mise en place d'un CDN

Mesure avant d'optimiser : le résultat d'un test de charge avant et après tes changements est la meilleure preuve. Adapte les index aux requêtes les plus fréquentes, ajoute un cache Redis avec une invalidation bien pensée, et des en-têtes de cache pour le CDN. L'autoscaling ajoute des réplicas selon des métriques comme le CPU, donc l'application doit être sans état : les sessions et le cache vivent dans Redis, pas dans la mémoire du processus.

4. Surveillance (2-3 heures)

  • Health checks
  • Collecte de métriques
  • Système d'alertes
  • Agrégation des logs

Sépare les endpoints de santé en liveness et readiness, expose les métriques pour Prometheus, et écris les logs en JSON avec un identifiant de requête. Une alerte ne doit réveiller quelqu'un que lorsqu'il faut agir : une alarme trop bruyante cesse vite d'être entendue.

5. Sauvegarde et récupération (1-2 heures)

  • Sauvegardes automatiques
  • Plan de reprise après sinistre
  • Vérifications de l'intégrité des données

Lance les sauvegardes automatiquement, fixe ton RTO et ton RPO, puis effectue une restauration complète sur un environnement neuf et note combien de temps elle a pris.

Critères d'évaluation

  • Complétude - tous les composants fonctionnent ensemble
  • Sécurité - des protections adaptées à chaque couche, du TLS aux secrets
  • Performances - l'application supporte le trafic de production, ce que confirme un test de charge
  • Surveillance - une observabilité complète : métriques, logs et alertes
  • Documentation - des runbooks de déploiement et de restauration

Le mentor évaluera le projet à partir du dépôt, donc le README doit contenir les commandes de lancement, une description de l'architecture et les résultats du test de restauration. Je te recommande d'écrire le runbook en même temps que la configuration, et non à la fin : ce que tu ne notes pas tout de suite ne sera plus qu'une supposition à trois heures du matin.

Bonne chance, légat ! Ta légion compte sur toi, et tu enverras le système terminé à ton mentor à la fin du module.

Code de cette leçon : deployment-project/docker-compose.yml
1# PROJET : déploiement complet en production d'une application NestJS
2
3version: '3.8'
4
5services:
6  # === API NestJS ===
7  api:
8    build:
9      context: .
10      dockerfile: Dockerfile
11    container_name: roman-api
12    restart: unless-stopped
13    ports:
14      - "4000:4000"
15    environment:
16      NODE_ENV: production
17      PORT: 4000
18      MONGO_URI: mongodb://mongo:27017/roman_empire
19      REDIS_HOST: redis
20      REDIS_PORT: 6379
21      JWT_SECRET: ${JWT_SECRET}
22      ALLOWED_ORIGINS: https://roman-empire.com
23    depends_on:
24      mongo:
25        condition: service_healthy
26      redis:
27        condition: service_healthy
28    healthcheck:
29      test: ["CMD", "node", "-e",
30        "require('http').get('http://localhost:4000/health', (r) => { process.exit(r.statusCode === 200 ? 0 : 1) })"]
31      interval: 30s
32      timeout: 10s
33      retries: 3
34      start_period: 40s
35    networks:
36      - roman-network
37
38  # === MongoDB ===
39  mongo:
40    image: mongo:7
41    container_name: roman-mongodb
42    restart: unless-stopped
43    volumes:
44      - mongo-data:/data/db
45      - ./scripts/backup.sh:/scripts/backup.sh
46    environment:
47      MONGO_INITDB_DATABASE: roman_empire
48    healthcheck:
49      test: ["CMD", "mongosh", "--eval", "db.runCommand('ping').ok"]
50      interval: 10s
51      timeout: 5s
52      retries: 5
53    networks:
54      - roman-network
55
56  # === Redis Cache ===
57  redis:
58    image: redis:7-alpine
59    container_name: roman-redis
60    restart: unless-stopped
61    command: redis-server --appendonly yes
62    volumes:
63      - redis-data:/data
64    healthcheck:
65      test: ["CMD", "redis-cli", "ping"]
66      interval: 10s
67      timeout: 3s
68      retries: 3
69    networks:
70      - roman-network
71
72  # === Nginx Reverse Proxy ===
73  nginx:
74    image: nginx:alpine
75    container_name: roman-nginx
76    restart: unless-stopped
77    ports:
78      - "80:80"
79    volumes:
80      - ./nginx.conf:/etc/nginx/nginx.conf:ro
81    depends_on:
82      - api
83    networks:
84      - roman-network
85
86# Volumes
87volumes:
88  mongo-data:
89    driver: local
90  redis-data:
91    driver: local
92
93# Network
94networks:
95  roman-network:
96    driver: bridge
97
98# Commandes :
99# docker-compose up -d        # Run
100# docker-compose logs -f api  # Logs API
101# docker-compose down         # Stop
102# docker-compose ps           # Status
103

Tu as repéré une erreur dans cette leçon ?