Telecharger cet article en PDF

Transcription

Telecharger cet article en PDF
Tuto: déploiement d'un projet
Django
20 décembre 2015 | [u'Systeme'] par VulgaireDev
Voici les prérequis :
- avoir un projet django fonctionel en local
- avoir un serveur auquel on a accès via ssh. Ça marche très bien avec un VPS
aussi, ce qui ne coûte pas grand chose : de l'ordre de quelques euros par mois
pour un serveur sur lequel vous pouvez installer ce que vous voulez + plusieurs
Go d'espace, ça peut être vraiment intéressant (https://www.ovh.com/fr/vps/ par
exemple).
- un peu de temps
Nous allons donc faire cette mise en prod, avec un serveur nginx + gunicorn.
Connectons-nous via ssh au serveur.
ssh [email protected]
C'est parti.
Comment ça marche en gros
On va installer la triplette django+nginx+gunicorn sur le serveur. En gros nginx
est le serveur HTTP qui se charge de recevoir les requêtes du même nom, va
communiquer avec gunicorn, qui lui-même communique avec django via la norme
wsgi. Ci-dessous un schéma récapitulatif pompé chez sam et max (http://
sametmax.com/quest-ce-que-wsgi-et-a-quoi-ca-sert/)
En parallèle, on va installer une base de données MySQL, pour stocker nos
données, avec laquelle django va communiquer. Pour une application plus
importante où on souhaite répartir la charge, on conseille de ne pas avoir et la
base de données et le serveur applicatif sur la même machine, mais ici on s'en
contentera largement (laaargement).
Mettre son système à jour
sudo apt-get update
sudo apt-get upgrade
Installer MySQL
J'ai choisi MySQL comme base de donné, mais on peut tout aussi bien prendre
MariaDB, PostgreSQL, Oracle etc.
On télécharge MySQL
sudo apt-get install mysql-server libmysqlclient-dev
Puis:
sudo mysql_install_db
Et enfin:
sudo mysql_secure_installation
Il faudra répondre à quelques simples questions, telles que définir un compte
administrateur et son mot de passe.
On va maintenant créer un nouvel utilisateur pour la BD
On se log en tant qu'admin dans le shell MySQL:
mysql -u root -p
On crée la base de données relative à notre projet,
CREATE DATABASE monProjet CHARACTER SET UTF8;
puis on créé un nouvel utilisateur, qui aura les droits sur monProjet, et pas sur
tout MySQL comme le compte admin précédemment créé
CREATE USER userMonProjet@localhost IDENTIFIED BY 'monMotDePasse';
On lui donne les droits (lecture, écriture, exécution) sur monProjet:
GRANT ALL PRIVILEGES ON monProjet.* TO userMonProjet@localhost;
Et on valide
FLUSH PRIVILEGES;
Puis on quitte le shell MySQL
exit
NB: Pour ce qui est de l'interfaçage avec django, voir la fin de ce tuto dans
"masquer ses mots de passe"
Créer un nouvel User
Maintenant on va créer un nouvel utilisateur : les applications seront lancées
sous sa juridiction. Ainsi, en cas de faille de sécurité, on peut espérer que
l'attaquant ne puisse causer de dommages que là où ce nouvel utilisateur peut
agir.
sudo useradd --system --shell /bin/bash --home /webApps webUser
(le dernier paramètre est le nom du nouvel user, et le --home définit le répertoire
home, celui sur lequel on arrive en faisant "cd ~", de webUser)
Installer VirtualEnv et pip
VirtualEnv est un outil qui permet de créer un environnement virtuel Python. En
gros, ça veut dire que toutes les installations python faites lorsqu'on est dans un
environnement virtuel ne seront disponibles que dans cet environnement virtuel,
et pas en-dehors. Ainsi, on peut avoir sur le même système plusieurs projets dont
les versions de python, de django etc sont différentes. Un autre avantage est que
si on se foire dans l'installation, ce n'est pas toute l'installation linux qui est
compromise, mais simplement le virtualEnv ! (c'est assez pratique)
Mieux encore que VirtualEnv, nous allons installer virtualenvwrapper, qui est
juste une surcouche nous permettant d'utiliser plus simplement les
environnements virtuels.
Pip, quand à lui, est le gestionnaire de paquets de python (plus d'infos ici http://
sametmax.com/votre-python-aime-les-pip/)
D'abord on installe des outils de bases pour python
sudo apt-get install python-setuptools
Parmi eux, se trouve easy_install, qui est comme pip mais en moins bien (ne gère
pas la désinstallation des paquets par exemple : ca s'appelle easy_install pas
easy_uninstall).
On l'utilise pour installer pip:
easy_install pip
Maintenant on installe virtualenvwrapper :
sudo pip install virtualenvwrapper
On va maintenant ecrire dans le .profile afin que le virtualenvwrapper se lance
quand on se log dans linux:
nano ~/.profile
puis on écrit à la fin:
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
On recharge le fichier de démarrage:
. ~/.profile
Enfin, il ne nous reste plus qu'à créer notre environnement virtuel :
mkvirtualenv virtualMonProjet --no-site-packages
--no-site-packages permet de n'avoir que python et pip dans son environnement.
Pour se placer dans l'environnement virtuel, il suffit de faire:
workon virtualMonProjet
Vous verrez alors écrit (virtualMonProjet)root@monserveur dans la console. Si
vous souhaitez sortir de l'environnement tapez "deactivate".
Attention pour la suite soyez bien dans votre environnement virtuel.
Installer Django et créer le dossier Projet
Ca devrait rouler tout seul étant donné ce qu'on a fait avant :
sudo pip install django
Maintenant on va choisir où mettre notre projet, on peut choisir de le mettre dans
/webApps:
sudo mkdir -p /webapps
sudo chown webUser /webapps
Maintenant on va rapatrier notre projet depuis le local vers le serveur, en local,
on tape:
scp -r monProjet root@serveur:/webApps
Et une fois sur le serveur on définit webUser comme propriétaire de ce dossier:
sudo chown webuser /webApps/monProjet/
Installer Gunicorn
On va donc maintenant installer Gunicorn, qui va communiquer avec django
comme on a vu dans le schéma plus haut.
sudo pip install gunicorn
Il faut configurer gunicorn dans un fichier avant de la lancer. On va le mettre
dans /webApps/monProjet/bin
nano /webApps/monProjet/bin/gunicorn_start
Je vous file un fichier de config, reste juste à l'adapter:
#!/bin/bash
monProjet/
DJANGODIR=/webapps/
# Django project directory
ur
rkers comme ca
echo "Start $NAME en tant que `whoami`"
# On active l'environnement virtuel
source /var/www/.virtualenvs/virtualVulgaireDev/bin/activate
home de webuser
source /webApps/.profile
# lance Django Unicorn
cd $DJANGODIR
exec gunicorn monProjet.wsgi \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER \
Pour gérer gunicorn (restart, stop etc), on va utiliser supervisor. Celui-ci permet
de relancer automatiquement les applications qu'on lui donne en cas de crash
serveur, et de gérer des scripts (ici gunicorn_start).
sudo apt-get install supervisor
Pour spécifier un fichier de configuration pour supervisor relatif à gunicorn, il
faut l'écrire dans /etc/supervisor/conf.d
sudo nano /etc/supervisor/conf.d/hello.conf
Puis on configure de cette manière ceci :
[program:monProjet]
command = /webapps/monProjet/bin/
gunicorn_start ; Command to start app
user = webUser ; User to run as
stdout_logfile = /var/log/gunicorn/
gunicorn.log ; Where to write log messages
redirect_stderr = true ; Save stderr in the same log
coding
Puis on crée l'endroit où les logs doivent s'écrire :
mkdir -p /var/log/gunicorn
Enfin, on demande à supervisor de recharger ses fichiers de config.
sudo supervisorctl reread
Et on peut maintenant redémarrer gunicorn à notre guise :
sudo supervisorctl restart monProjet
Installer Nginx
Il ne reste plus qu'à installer le serveur Nginx, qui intercepte les requêtes HTTP
pour les envoyer au couple (Gunicorn,Django)
sudo apt-get install nginx
sudo service nginx start
Si vous tapez votre nom de domaine, vous devriez arriver sur une page disant que
nginx est présent.
On doit configurer nginx pour ce projet :
nano /etc/nginx/sites-available/monProjet
et encore une fois un fichier de configuration à adapter à votre projet:
# Configuration du server
server {
listen
80;
server_name www.monDomaine.fr monDomaine.fr;
charset
utf-8;
access_log /var/log/nginx/monProjet.access.log;
error_log /var/log/nginx/monProjet.error.log;
proxy_connect_timeout 300s;
proxy_read_timeout 300s;
# Fichiers media et statiques, délivrés par nginx directement
location /media {
alias /webapps/monProjet/media;
}
location /static {
alias /webapps/monProjet/static;
}
location / {
proxy_pass http://127.0.0.1:8000; # Pass to Gunicorn
proxy_set_header X-RealIP $remote_addr; # get real Client IP
}
}
Il faut maintenant faire en sorte que le site soit disponible, pour cela il faut créer
un lien symbolique dans sites-enable:
sudo ln -s /etc/nginx/sites-available/monProjet /etc/nginx/sitesenabled/monProjet
Puis on peut redémarrer le service nginx.
sudo service nginx restart
Maintenant ca devrait presque marcher, il faut juste ne pas oublier de mettre le
debug = FALSE dans setting.py, et de bien faire l'interfaçage avec la BDD (juste
après)
Masquer ses mots de passe
Avoir ses mots de passe directement écrits dans le setting.py c'est nul. On ne
peut pas publier son code sur github ou autre sans que tout le monde les
connaisse ce qui serait dramatique (ou alors on passe par un .gitignore), et
franchement voir mes mots de passe écrits en dur comme ça, ça me met mal à
l'aise.
Une solution est de les écrire dans le .profile, en bash, pour qu'à chaque fois
qu'un utilisateur arrive, les mots de passe soient en variable d'environnement. On
va écrire dans le .profile (si vous voulez plus d'explications sur le comment du
pourquoi on écrit dans .profile et pas dans .bashrc http://superuser.com/
questions/183870/difference-between-bashrc-and-bash-profile)
nano /home/webUser/.profile
Puis on ajoute ceci à la fin, ce qui va rendre cette variable globale au système
linux (variable d'environnement):
export MONSITE_DB_PASSWORD='monMotdePasse'
Maintenant on ajoute une ligne à notre fichier gunicorn_start dans /webApps/
MonProjet/bin/gunicorn_start, pour qu'à chaque fois que le serveur se lance il
exécute .profile.
source /home/webUser/.profile
Enfin, il ne reste plus qu'à les récupérer dans le fichier setting.py, ici dans la
connexion à la BD.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'monProjet',
'USER': 'adminMonProjet',
'PASSWORD': os.environ.get
nnement
'HOST': 'localhost',
'PORT': '',
}
}
Utiliser git pour envoyer son projet sur le
serveur
On utilise git pour versionner son projet, et/ou pour travailler à plusieurs le plus
souvent. Mais ce qui est cool c'est qu'on peut aussi l'utiliser pour envoyer notre
projet sur le serveur. Vous faites vos modifications en local, tout marche bien,
vous faites un commit, et bam vous balancez tout sur la prod, rien de plus à faire.
On commence par créer un repo git un peu particulier : un --bare, qui ne contient
aucun fichier source
sudo mkdir -p /var/repo/monProjet.git
cd /var/repo/monProjet.git
git init --bare
Maintenant que c'est fait, vous verrez un dossier hook dans le dossier
monProjet.git. On peut y définir des fichiers qui vont intercepter les push, et faire
des actions. Ici on va définir un fichier qui intercepte les push de l'utilisateur, et
rediriger ce qui a été push non pas vers /var/repo/monProjet.git, mais vers /
webApps/monProjet
nano hooks/post-receive
puis on écrit dedans:
#!/bin/sh
git --work-tree=/webApps/monProjet --git-dir=/var/repo/
monProjet.git checkout -f
"--git-dir" spécifie le repertoire source, "--work-tree" spécifie l'endroit vers lequel
on veut rediriger le push. On remarque que c'est encore un checkout (git utilise
souvent cette commande) : ici il ne signifie pas "changer de branche", mais
"mettre à jour l'espace de travail"
On ajoute les droits d'execution :
chmod +x hooks/post-receive
Maintenant, on se met sur la machine local, et on init un repo git dans notre
dossier
cd /chemin/vers/projet/monProjet
git init
Et maintenant, on ajoute une "remote" à notre repo :
git remote add prod ssh://[email protected]/var/repo/
monProjet.git
Et voilà, à chaque fois qu'on voudra envoyer notre projet en prod, on fera :
git push prod master
(bien sûr ca ne push que les commit, ça reste un dépôt git hein)
Pour finir
J'espère que le tuto vous aura permis de bien vous débrouiller, et que vous saurez
résoudre vos problèmes, car soyons sérieux, si vous n'êtes pas habitués à
effectuer des mises en prod, il y en aura surement. Méfiez-vous notamment des
droits linux sur les dossiers et fichiers, parfois vous ne les avez pas et ça plante.
Bon courage!
Sources :
http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenvsupervisor/
https://www.digitalocean.com/community/tutorials/how-to-set-up-automaticdeployment-with-git-with-a-vps
https://www.digitalocean.com/community/tutorials/how-to-use-mysql-or-mariadbwith-your-django-application-on-ubuntu-14-04
http://sametmax.com/votre-python-aime-les-pip/