Django en production : Gunicorn lancé avec dix-sept workers « par formule internet », Nginx qui proxy tout — y compris /static/ — vers Gunicorn. Le CPU Gunicorn monte à 100 % pendant un crawl d'images. Correction : nginx alias /static/ et workers réduits à cinq — la latence API est divisée par trois.
La stack Django standard en production ressemble à ceci :
Client → Nginx (TLS, compression, fichiers statiques, limitation débit) → Gunicorn (WSGI) → Django
Gunicorn n'est pas un serveur web public — c'est un gestionnaire de processus WSGI. Nginx n'exécute pas Python — il ne doit jamais interpréter Django.
Dimensionner Gunicorn avec mesure, pas avec une formule seule
Formule de départ sur un VPS deux cœurs : workers = (2 × cores) + 1 → cinq workers.
Affinez ensuite selon :
- RAM : comptez 100 à 300 Mo par worker Django selon l'application.
--timeout 30: tue un worker bloqué — un rapport long doit passer par Celery, pas par HTTP.--graceful-timeout: aligné surproxy_read_timeoutnginx.--max-requests 1000 --max-requests-jitter 50: recycle les workers pour limiter les fuites mémoire légères.
gunicorn myproject.wsgi:application \
--bind unix:/run/gunicorn.sock \
--workers 5 \
--timeout 30 \
--access-logfile -
Configuration nginx type
location /static/ {
alias /var/www/myproject/static/;
expires 30d;
}
location /media/ {
alias /var/www/myproject/media/;
}
location / {
proxy_pass http://unix:/run/gunicorn.sock;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Configurez ALLOWED_HOSTS et SECURE_PROXY_SSL_HEADER dans Django pour que HTTPS derrière nginx soit correctement reconnu.
systemd, socket et déploiement sans coupure
Une unité gunicorn.service avec User=www-data et Restart=always assure la relance automatique. Les permissions du socket Unix doivent permettre à nginx d'y accéder.
Au déploiement : collectstatic, puis reload Gunicorn (HUP gracieux). Les workers terminent les requêtes en cours avant de charger le nouveau code — pas de coupure brutale si les timeouts sont alignés.
Workers asynchrones : prudence
gevent peut aider si le profilage montre une attente réseau importante (appels API externes). Ce n'est pas le choix par défaut pour un e-commerce chargé en base de données — sync avec un pool de connexions Postgres bien dimensionné reste plus prévisible.
Pour les tâches longues, consultez Celery et files d'attente.
Hébergement et contraintes produit
Un VPS est le minimum pour un Django sérieux en production. Les PaaS (Railway, Clever Cloud) abstraient Gunicorn — vous configurez un Procfile ou équivalent. Le mutualisé Python reste rare et ne permet généralement pas de contrôler le nombre de workers.
Le sommet : Gunicorn surchargé sert souvent ce que Nginx donnerait gratuitement
Auditez vos logs nginx : si plus de zéro pour cent des requêtes statiques ou médias passent vers l'upstream Gunicorn, corrigez les alias avant d'ajouter des workers.
Décider et avancer sans angle mort
Pour remettre une stack Django sur des bases saines :
- Configurez nginx pour servir
/static/et/media/en alias — Gunicorn ne doit traiter que le dynamique. - Dimensionnez les workers à partir du nombre de cœurs et de la RAM mesurée, pas d'une formule copiée-collée.
- Alignez les timeouts entre nginx et Gunicorn pour éviter les coupures en plein traitement.
- Externalisez les exports et rapports de plus de trente secondes vers Celery ou une file d'attente.
- Scriptez un reload gracieux au déploiement — collectstatic, HUP, smoke test HTTP.
Pour le pool de connexions Postgres, voir Connection pooling. Pour comparer les hébergeurs VPS, parcourez notre annuaire.
Questions fréquentes
Combien de workers Gunicorn ?
Commencez avec (2 × cœurs) + 1, puis ajustez selon la RAM et les mesures sous charge réelle.
Nginx sert-il les fichiers static Django ?
Oui — collectstatic vers un dossier alias nginx. Gunicorn ne doit pas servir CSS, JS ou médias.
Socket Unix ou TCP ?
Socket Unix sur la même machine ; TCP localhost pour les architectures conteneurisées.
sync vs gevent ?
sync par défaut ; gevent seulement si le profilage prouve une attente réseau dominante.
Gunicorn exécute Django ; Nginx exécute le reste — confondre les deux, c'est payer Python pour servir des PNG.