Gérer, monitorer et déployer des applications Node.js en production avec PM2 — process manager, clusters, logs, déploiement automatisé et survie aux redémarrages.
PM2 embarque un système de déploiement intégré. L'idée : définir dans ecosystem.config.js comment se connecter à votre serveur, quoi faire au déploiement, et lancer tout ça avec pm2 deploy. Pratique pour les petits projets sans CI/CD.
module.exports = {
apps: [
{
name: 'api',
script: './dist/index.js',
instances: 'max',
exec_mode: 'cluster',
env_production: {
NODE_ENV: 'production',
PORT: 3000,
},
},
],
deploy: {
production: {
user: 'deploy', // utilisateur SSH
host: ['192.168.1.100'], // IP ou hostname du serveur
ref: 'origin/main', // branche à déployer
repo: 'git@github.com:org/repo.git', // repository
path: '/var/www/api', // dossier sur le serveur
'pre-deploy-local': '', // commande locale avant déploiement
'post-deploy':
'npm ci --only=production && npm run build && pm2 reload ecosystem.config.js --env production',
'pre-setup': '',
},
},
}# Initialise le dossier sur le serveur (clone le repo, crée la structure)
pm2 deploy production setupPM2 se connecte en SSH, clone le repo dans /var/www/api, et crée les dossiers source, current, shared.
pm2 deploy productionSéquence exécutée par PM2 :
git pull origin main dans le dossier sourcecurrent vers le nouveau releasepost-deploy — ici npm ci && npm run build && pm2 reloadPour la plupart des projets, PM2 deploy est remplacé avantageusement par un workflow GitHub Actions qui se connecte en SSH et exécute les commandes directement. C'est plus transparent et plus facile à déboguer.
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.SERVER_HOST }}
username: deploy
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/api
git pull origin main
npm ci --only=production
npm run build
pm2 reload ecosystem.config.js --env production
pm2 saveChaque push sur main déclenche le déploiement automatiquement. Aucune intervention manuelle.
Si votre app tourne dans un conteneur Docker, PM2 peut gérer le cycle de vie du container — mais dans ce cas, l'orchestrateur standard reste Docker Compose ou Kubernetes. PM2 est moins pertinent quand Docker est déjà là.
L'exception : pm2-docker ou pm2 start app.js --no-daemon dans un Dockerfile pour gérer plusieurs processus Node dans un même container, avec hot-reload et logs centralisés.
FROM node:20-alpine
RUN npm install -g pm2
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]pm2-runtime (alias pm2 start --no-daemon) est la commande prévue pour les containers — elle ne tourne pas en background, ce qui est ce que Docker attend du PID 1.
Ne jamais mettre les secrets dans ecosystem.config.js. Trois approches :
Option 1 : fichier .env sur le serveur
# Sur le serveur, hors du repo
echo "DATABASE_URL=postgresql://..." >> /var/www/api/.env
echo "JWT_SECRET=..." >> /var/www/api/.env// Dans votre app
import dotenv from 'dotenv'
dotenv.config()Option 2 : variables d'environnement système
# Dans /etc/environment ou le .bashrc de l'utilisateur deploy
export DATABASE_URL="postgresql://..."
export JWT_SECRET="..."PM2 hérite des variables d'environnement du shell qui l'a lancé.
Option 3 : référencer des variables système dans ecosystem.config.js
env_production: {
NODE_ENV: 'production',
PORT: 3000,
DATABASE_URL: process.env.DATABASE_URL, // lu depuis l'environnement système
}Si le déploiement casse quelque chose, pm2 deploy gère les releases avec symlinks — rollback en une commande :
pm2 deploy production revert 1 # revenir au release précédentAvec le déploiement SSH manuel, le rollback demande plus de travail. Une pratique courante : garder le build précédent sur le serveur et avoir un script de rollback.
# Sur le serveur
ls /var/www/releases/
# release-20260622-143201/
# release-20260621-091532/ ← précédent
ln -sfn /var/www/releases/release-20260621-091532 /var/www/current
pm2 reload apiPM2 couvre tout le cycle de vie d'une application Node.js en production : démarrage, surveillance, clustering, logs, persistance et déploiement. L'essentiel tient en deux fichiers — ecosystem.config.js dans le repo, et les commandes pm2 startup && pm2 save sur le serveur.