Je vois souvent passer des questions sur le forums ou autres fils de discussion concernant la mise en production d'un projet Django.
Ici je vais présenter une façon de faire, utilisant Nginx Gunicorn et Supervisord .
Prérequis
Sur une Débian toute fraiche,
Nginx
sudo apt-get install nginx
Virtualenv
Car nous travaillons toujours avec un environnement virtuel, dans lequel nous allons y installer les dépendances de notre projet.
Ce qui permet de ne pas avoir de conflit de version avec d'autres éventuels projets déjà en prod.
pip install virtualenv virtualenvwrapper
Note : Si vous n'avez pas l'outil pip de disponible, installez-le comme ceci
sudo apt-get install python-setuptools sudo easy_install pip
Puis dans votre fichier ~/.bashrc , ajoutez les lignes suivantes, pour l'autocompletion
export VIRTUALENVWRAPPER_VIRTUALENV_ARGS='--no-site-package' export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh
Gunicorn
Pourquoi pas utiliser uWSGI ? humm ... car je préfère Gunicorn qui me donne toute satisfaction sur mes projets en prod. donc ... pourquoi pas !
sudo apt-get install libevent-dev pip install gunicorn
Supervisor
Installation simple :
sudo pip install supervisor
Récupération du fichier de conf par défaut
echo_supervisord_conf > /etc/supervisord.conf
Dans le fichier de conf, afin de pouvoir manager votre projet via l'interface web, il faut dé-commenter et paramétrer les lignes suivantes
[inet_http_server] ; inet (TCP) server disabled by default port=*:9001 ; (ip_address:port specifier, *:port for all iface) username=user ; (default is no username (open server)) password=123 ; (default is no password (open server))
Note: Changer le username et password évidemment
L'interface web sera disponible à l'adresse : http://ipduserveur:9001
Pour le lancement automatique au démarrage du système, vous pouvez utiliser ces scripts d'init:
Installer votre projet
Notre environnement est prêt, nous allons commencer par installer le projet Django dans l’environnement virtuel.
Création du virtualenv
mkvirtualenv monprojet
Si vous utilisez git, cloner votre projet, sinon, copier le à l'endroit que vous souhaitez, ( pour l'exemple ce sera /var/www/monprojet )
Installation des dépendances du projet
si vous utilisez également les environnements virtuels pour développer ( ce que je conseille ) vous pouvez alors enregistrer la liste des libs python installées dans cette environnement, afin de pouvoir également les installer ( avec la même version ) sur un autre serveur.
Pour avoir la liste des libs :
pip freeze > requirements.txt
puis sur votre serveur, pour installer les libs depuis un export freeze :
pip install -r requirements.txt
Configuration de Django
Il vous faudra peut-être toucher un peu à votre fichier settings.py pour le passer du mode debug au mode production.
Personnellement j'utilise une autre subtilité qui me permet de ne pas avoir à toucher au fichier settings.py ( j'expliquerai celà dans un autre billet ) .
N'oubliez pas de vérifier le paramètre STATIC_ROOT
STATIC_ROOT = '/var/www/static_monprojet/'
C'est le répertoire ou seront copiés les fichiers statiques du projet, pour ensuite être servis par Nginx
Ce répertoire DOIT EXISTER
Une fois le répertoire créé, nous allons y "placer/lier" les fichiers statiques du projet
python manage.py collectstatic --link
Perso je préfère y mettre des liens symboliques .. ( les gouts et les couleurs ... )
Liaison du projet avec Gunicorn
Nous allons créer un fichier dans notre projet qui sera utilisé pour le lancement du/des process Gunicorn ( vous devrez adapter les valeurs dans ce script )
vim /var/www/monprojet/monprojet/gunicorn.sh
Et voici le contenu
#!/bin/bash set -e NUM_WORKERS=2 USER=www-data GROUP=www-data ADDRESS=127.0.0.1:5002 cd /var/www/monprojet source /home/monuser/.virtualenvs/monprojet/bin/activate exec gunicorn monprojet.wsgi:application -w $NUM_WORKERS --bind=$ADDRESS \ --user=$USER --group=$GROUP --log-level=debug
Puis on le rend exécutable
chmod 777 /var/www/monprojet/monprojet/gunicorn.sh
Configuration Supervisord
Notre projet est prêt, afin de lancer Gunicorn automatiquement, nous allons utiliser supervisord, qui en plus de s'occuper de démarrer le projet automatiquement au démarrage du système, va aussi le relancer en cas de crash, gérer les logs et vous donner la main pour arrêter ré-demarrer les process, via l'interface web ou en mode console.
Ajoutez à la fin du fichier de configuration /etc/supervisord.conf les lignes suivantes ( paramètres à adapter selon votre cas )
[program:guni_monprojet] directory=/var/www/monprojet/monprojet user = www-data autostart=true autorestart=true stdout_logfile=/var/log/monprojet.log redirect_stderr=true stopsignal=QUIT command = /var/www/monprojet/monprojet/monprojet.sh
Ne reste plus qu'à redémarrer supervisor pour prendre en compte la nouvelle config.
Pour le lancer manuellement
sudo supervisord -c /etc/supervisord.conf
Vhost Nginx
Dernier point, la création du vhost de Nginx, pour diriger les requêtes vers Gunicorn qui écoute sur le port 5002 ( il est aussi possible d'utiliser un fichier socket à la place )
vim /etc/nginx/sites-enabled/monprojet
Et voilà le contenu ( fonctionnel, mais vous pouvez l'adapter )
upstream us_monprojet { server 127.0.0.1:5002; } server { listen 80; root /var/www/monprojet; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain application/xml text/css text/javascript application/x-javascript application/x-shockwave-flash video/x-flv; gzip_disable "MSIE [1-6]\."; server_name monprojet.com; charset utf-8; client_max_body_size 75M; location ~ /\.ht { deny all; } location /favicon.ico { alias /var/www/monprojet/monprojet/static/favicon.ico; if (-f $request_filename) { access_log off; expires max; } } location /media { alias /var/www/monprojet/monprojet/media; if (-f $request_filename) { access_log off; expires max; } } location /static { alias /var/www/static_monprojet/; if (-f $request_filename) { access_log off; expires max; } } location / { if (-f $request_filename) { access_log off; expires max; } #gunicornParams if (!-f $request_filename) { proxy_pass http://us_monprojet; break; } proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
Ne reste plus qu'à activer le vhost, et relancer nginx
ln -s /etc/nginx/sites-available/monprojet /etc/nginx/sites-enabled/ service nginx reload