Déployer son app Node.js
Variables d'environnement
Une application Node.js a besoin de configurations qui changent selon l'environnement : clés API, URL de base de données, ports d'écoute. On ne code jamais ces valeurs en dur dans le source. On utilise des variables d'environnement.
Node.js expose les variables d'environnement via l'objet process.env.
Par exemple, le port d'écoute devient process.env.PORT.
const express = require('express');
const app = express();
// Utilise la variable d'env PORT, sinon 3000 par défaut
const PORT = process.env.PORT || 3000;
const DB_URL = process.env.DATABASE_URL || 'mongodb://localhost/madb';
const API_KEY = process.env.API_KEY; // pas de valeur par défaut — obligatoire
app.listen(PORT, () => {
console.log(`Serveur démarré sur le port ${PORT}`);
});
En développement, on stocke ces valeurs dans un fichier .env à la racine du projet.
Le package dotenv charge ce fichier automatiquement au démarrage.
npm install dotenv
PORT=3000
DATABASE_URL=mongodb://localhost/madb
API_KEY=abc123supersecret
JWT_SECRET=monSecretJWT
// À placer en toute première ligne, avant tout require()
require('dotenv').config();
const express = require('express');
// process.env.PORT est maintenant disponible
Ne jamais commiter le fichier .env !
Il contient des secrets (clés API, mots de passe).
Ajoute .env dans ton .gitignore avant le premier commit.
Crée en revanche un fichier .env.example sans valeurs réelles pour documenter les variables nécessaires.
Mode production
La variable NODE_ENV indique à Node.js et aux frameworks dans quel contexte tourne l'app.
En production, Express active des optimisations : cache des vues, messages d'erreur réduits, compression.
# Définir NODE_ENV avant de lancer l'app
NODE_ENV=production node server.js
# Ou via un script npm dans package.json
# "scripts": { "start": "NODE_ENV=production node server.js" }
const isProd = process.env.NODE_ENV === 'production';
if (!isProd) {
// Logs détaillés uniquement en développement
app.use(require('morgan')('dev'));
}
// En production : morgan 'combined' pour les logs Apache-style
if (isProd) {
app.use(require('morgan')('combined'));
}
PM2 — gestionnaire de processus
Si ton serveur Node.js plante, il s'arrête. PM2 est un gestionnaire de processus qui relance automatiquement ton app en cas de crash, gère les logs, et permet de démarrer l'app automatiquement au redémarrage du serveur.
# Installer PM2 globalement
npm install -g pm2
# Démarrer l'application
pm2 start server.js --name mon-app
# Voir l'état de toutes les apps
pm2 list
# Consulter les logs en temps réel
pm2 logs mon-app
# Redémarrer après une mise à jour du code
pm2 restart mon-app
# Stopper l'application
pm2 stop mon-app
# Activer le démarrage automatique au boot du serveur
pm2 startup
pm2 save
PM2 en production : utilise pm2 start server.js --name mon-app -- --env production
ou crée un fichier ecosystem.config.js pour centraliser la configuration
(nom, script, variables d'environnement, nombre d'instances).
La commande pm2 monit affiche un tableau de bord CPU/RAM en temps réel.
Déployer sur un VPS Linux
Un VPS (Virtual Private Server) te donne un serveur Linux dédié. Tu y as un accès root complet et tu peux y héberger plusieurs applications. Voici le flux classique pour y déployer une app Node.js.
# Se connecter au VPS en SSH
ssh user@adresse-ip-vps
# Installer nvm (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
# Installer Node.js LTS via nvm
nvm install --lts
nvm use --lts
# Cloner le dépôt Git
git clone https://github.com/toi/mon-app.git
cd mon-app
# Installer les dépendances (sans devDependencies)
npm install --omit=dev
# Créer le fichier .env de production
nano .env
# Lancer avec PM2
pm2 start server.js --name mon-app
pm2 save
Pour exposer l'app sur le port 80 (HTTP) ou 443 (HTTPS), on utilise nginx comme reverse proxy. Nginx reçoit les requêtes publiques et les redirige vers ton app Node.js.
server {
listen 80;
server_name mondomaine.fr www.mondomaine.fr;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
# Activer le site
ln -s /etc/nginx/sites-available/mon-app /etc/nginx/sites-enabled/
# Vérifier la configuration
nginx -t
# Recharger nginx
systemctl reload nginx
# Ajouter HTTPS avec Let's Encrypt (gratuit)
apt install certbot python3-certbot-nginx
certbot --nginx -d mondomaine.fr -d www.mondomaine.fr
Plateformes cloud simples
Un VPS demande de la maintenance. Les plateformes cloud modernes automatisent le déploiement : tu pousses ton code, elles construisent et déploient automatiquement.
Render
Connecte ton dépôt GitHub, choisis "Web Service", indique la commande de démarrage
(node server.js) et le tour est joué. Render déploie à chaque push.
Tier gratuit disponible avec mise en veille après inactivité.
Railway
Interface simple, détection automatique du langage. Railway lit ton
package.json et exécute npm start.
Variables d'environnement configurables dans l'interface.
Fly.io
Plus puissant, basé sur des conteneurs. Nécessite flyctl (CLI).
Déploiement en 2 commandes depuis le terminal.
# Installer flyctl
curl -L https://fly.io/install.sh | sh
# Initialiser l'app (crée fly.toml)
fly launch
# Déployer
fly deploy
# Consulter les logs
fly logs
Docker pour Node.js
Docker permet d'empaqueter ton app avec toutes ses dépendances dans un conteneur portable. Le même conteneur tourne en local, sur un VPS, ou sur n'importe quelle plateforme cloud.
# Image de base officielle Node.js LTS (légère)
FROM node:20-alpine
# Dossier de travail dans le conteneur
WORKDIR /app
# Copier package.json et package-lock.json en premier
# (optimisation du cache Docker : pas de npm install si rien n'a changé)
COPY package*.json ./
RUN npm install --omit=dev
# Copier le reste du code source
COPY . .
# Exposer le port utilisé par l'app
EXPOSE 3000
# Commande de démarrage
CMD ["node", "server.js"]
# Construire l'image (tag "mon-app:latest")
docker build -t mon-app .
# Lancer le conteneur en arrière-plan
# -p 8080:3000 = port local 8080 → port interne 3000
docker run -d -p 8080:3000 --name mon-app mon-app
# Consulter les logs du conteneur
docker logs mon-app
# Arrêter et supprimer le conteneur
docker stop mon-app && docker rm mon-app
Crée aussi un fichier .dockerignore pour éviter d'inclure node_modules
et .env dans l'image :
node_modules
.env
.git
*.log
npm-debug.log*
Checklist de production
Avant de mettre ton app en ligne, vérifie ces points essentiels.
Sécurité
- HTTPS : Let's Encrypt (gratuit) via nginx ou Certbot. Ne jamais exposer HTTP en production.
- CORS : restreindre les origines autorisées avec le package
cors. - Rate limiting : limiter les requêtes par IP avec
express-rate-limitpour éviter les abus. - Helmet : le package
helmetajoute des en-têtes HTTP de sécurité en une ligne. - Ne jamais exposer
process.envdans les réponses API.
Observabilité
- Logs : utilise
morganen modecombineden production. Redirige les logs PM2 vers des fichiers. - Monitoring :
pm2 monitpour le CPU/RAM. Pour aller plus loin : UptimeRobot (disponibilité), Sentry (erreurs). - Health check : expose un endpoint
GET /healthqui retourne200 OKpour que les load balancers vérifient que l'app tourne.
Robustesse
- Gérer les rejets de promesses non catchés avec
process.on('unhandledRejection', ...). - Activer le clustering PM2 (
pm2 start server.js -i max) pour utiliser tous les cœurs CPU. - Mettre en place une stratégie de backup pour la base de données.
require('dotenv').config();
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const app = express();
// Sécurité HTTP headers
app.use(helmet());
// CORS : autoriser uniquement le front officiel
app.use(cors({ origin: process.env.FRONTEND_URL }));
// Rate limiting : 100 requêtes max par IP par 15 minutes
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));
// Health check
app.get('/health', (req, res) => res.json({ status: 'ok' }));
// Rejets de promesses non gérés
process.on('unhandledRejection', (reason) => {
console.error('Unhandled rejection:', reason);
});
process.env.NOMpour lire une variable d'environnement.dotenvcharge le fichier.enven développement.- Ne jamais commiter
.env: ajoute-le dans.gitignoredès le début. NODE_ENV=productionactive les optimisations d'Express et conditionne les logs.- PM2 : relance automatique, logs persistants, démarrage au boot avec
pm2 startup && pm2 save. - Sur un VPS : Node via nvm, nginx en reverse proxy, HTTPS avec Certbot.
- Plateformes simples : Render, Railway, Fly.io — déploiement automatique depuis GitHub.
- Docker :
Dockerfile+.dockerignore,docker buildpuisdocker run. - Checklist production : HTTPS, Helmet, CORS restrictif, rate limiting, logs, health check
/health.