Nginx en reverse proxy + Gunicorn pour vos apps Django 4


Nginx est bien connu depuis quelques années. Puissant serveur HTTP, il peut être utilisé en tant que reverse proxy (mandataire inverse en Français) afin d’améliorer les performances.
Je vous copie/colle les avantages depuis Wikipédia parce que je suis une feignasse:

cache : le mandataire inverse ou (reverse proxy) peut décharger les serveurs Web de la charge de pages/objets statiques (pages HTML, images) par la gestion d’un cache local. La charge des serveurs Web est ainsi généralement diminuée, on parle alors d’« accélérateur web » ou d’« accélérateur HTTP ».
Intermédiaire de sécurité : le mandataire inverse protège un serveur Web des attaques provenant de l’extérieur. En effet, la couche supplémentaire apportée par les mandataires inverses peut apporter une sécurité supplémentaire. La ré-écriture programmable des URL permet de masquer et de contrôler, par exemple, l’architecture d’un site web interne. Mais cette architecture permet surtout le filtrage en un point unique des accès aux ressources Web.
Chiffrement SSL : le mandataire inverse peut être utilisé en tant que « terminateur SSL », par exemple par le biais de matériel dédié,
Répartition de charge : le mandataire inverse peut distribuer la charge d’un site unique sur plusieurs serveurs Web applicatifs. Selon sa configuration, un travail de ré-écriture d’URL sera donc nécessaire,
Compression : le mandataire inverse peut optimiser la compression du contenu des sites.

Pour résumé:

Visiteur > Web > Votre Serveur > Nginx > Gunicorn > Django

Dans la configuration suivante Nginx va servir les fichiers statiques (images, js, etc) et envoyer le reste des requêtes sur Gunicorn. Gunicorn est une interface WSGI entre le serveur HTTP (nginx) et Python, je n’ai pas trouvé de bonne explication sur WSGI à part le site officiel fait par des autistes.

Soit la configuration de Gunicorn suivante (on peut le lancer avec supervisor):

gunicorn_django  myapp.py --bind 127.0.0.1:8080 --log-file /var/log/myapp.gunicorn.log --log-level info --workers 2 --pid /tmp/myapp.pid  --worker-class gevent

Gunicorn va “écouter” en local sur le port 8080, il va logger des infos dans le fichier /var/log/myapp.gunicorn.log (pratique pour le debug si besoin).
Pour les workers et worker-class regardez la doc.

Configurer Nginx:
Dans la conf Nginx on va avoir.

server {
        listen       80;
        server_name mysite.com www.mysite.com;
 
        location /static/ {
            root  /home/myapp/prod;
            gzip  on;
        }
 
        location / {
            proxy_pass http://127.0.0.1:8080; # Pass to Gunicorn
            proxy_set_header X-Real-IP $remote_addr; # get real Client IP
        }
}

location va indiquer à Nginx ce qu’il faut faire lorsqu’il rencontre certaines URL.

Dans notre cas le location /static/ va dire à Nginx de servir directement tous les fichiers du répertoire /home/myapp/prod/static pour les URL http://mysite.com/static/… En général les images, javascript, etc.

Pour le reste location / va renvoyer les requêtes sur votre serveur Gunicorn qui va les traiter.

proxy_set_header sert à passer à Gunicorn certaines infos comme l’IP réelle du client (sinon Gunicorn verrait celle de NGinx 127.0.0.1).

De cette manière on ne surcharge pas Gunicorn pour servir nos fichiers statiques, on ajoute une protection (Nginx).
On peut éventuellement mettre en cache certaines pages mais je n’ai jamais utilisé cette option.
Nginx peut également distribuer la charge sur plusieurs serveurs et se charger de la compression des pages (gzip).

4 thoughts on “Nginx en reverse proxy + Gunicorn pour vos apps Django

  • VonTenia

    J’ai toujours configuré la prod pour mes projets Django sous cette forme, je ne connais même pas les autres configurations possible (à part le serveur de dev intégré)… Je viens donc de découvrir que j’utilise nginx en reverse proxy, je me coucherai un peu moins bête ce soir.

    Bon tuto en tout cas. Le plus dur dans l’affaire et quand on débute, c’est peut être de configurer gunicorn et supervisord (idée pour un futur article…).

  • Max Post author

    @von tenia

    Alors attends le prochain article je te sors la conf “Sandwich” avec Varnish à la place de Gunicorn et ce dernier en backend.

    +1 pour supervisor et gunicorn, je pensais que Sam en avait fait un d’ailleurs sur supervisor.
    Gunicorn c’est un peu l’usine à Gaz, je le connais pas bien, je sais juste que c un des meilleurs dans son registre.

  • Pas max

    Merci pour tes posts.

    Je me permet de te proposer un archi légèrement différente, je n’utilise pas gunicorn mais uwsgi qui en plus de supporter la lib event est bien plus facile à metre en œuvre et maintenir…

    Il a une tripotée de plugins inutiles, ou pas….

    Encore merci pour ton blog

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.