Update production

This commit is contained in:
jaguarondi 2016-05-15 21:26:57 +02:00
parent c22dfe89fd
commit 8bb5ec1730
5 changed files with 202 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -74,7 +74,7 @@ Il ne nous reste plus qu'à mettre à jour la DB. On commance par créer le fich
(gwift)gwift@gwift:~$ touch gwift/gwift/settings/local.py
Et le contenu de local.py, avec la clé secrète et les paramètres pour se connecter à la DB:
Et le contenu de local.py, avec la clé secrète, les paramètres pour se connecter à la DB et l'endroit où mettre les fichiers statics (voir point suivant):
.. code-block:: python
@ -88,6 +88,12 @@ Et le contenu de local.py, avec la clé secrète et les paramètres pour se conn
# Allowed host needed to be defined in production
ALLOWED_HOSTS = ["sever_name.com", "www.sever_name.com"]
# Be sure to force https for csrf cookie
CSRF_COOKIE_SECURE = True
# Same for session cookie
SESSION_COOKIE_SECURE = True
# DB
DATABASES = {
@ -100,6 +106,13 @@ Et le contenu de local.py, avec la clé secrète et les paramètres pour se conn
'PORT': '', # Set to empty string for default.
}
}
# Add static root
STATIC_ROOT = "/webapps/gwift/gwift/static"
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
Finalement, on peut mettre à jour la DB et créer un super utilisateur:
@ -108,6 +121,24 @@ Finalement, on peut mettre à jour la DB et créer un super utilisateur:
(gwift)gwift@gwift:~$ python manage.py migrate
(gwift)gwift@gwift:~$ python manage.py createsuperuser
Fichiers statics
================
Django n'est pas fait pour servir les fichiers statics. Tous les fichiers statics doivent donc être déplacés dans un répertoire pour que Nginx puisse les servir facilement.
On commence par créer le répertoire où mettre les fichiers statics comme configuré dans le fichier local.py:
.. code-block:: shell
(gwift)gwift@gwift:~$ mkdir /webapps/gwift/gwift/static
Et on utilise django pour copier tous les fichiers statics au bon endroit:
.. code-block:: shell
(gwift)gwift@gwift:~$ python manage.py collectstatic
Test
====

View File

@ -0,0 +1,82 @@
*************
Gunicorn
*************
Nous allons utiliser ``gunicorn`` comme serveur d'applications, le serveur fourni par django n'étant pas fait pour être utilisé en production.
Gunicorn a déjà été installé lors de la préparation de l'environnement. De même que ``setproctitle``, qui est nécessaire pour donner le nom de l'application aux processus python lancés par gunicorn.
Nous pouvons donc directement tester s'il fonctionne:
.. code-block:: shell
(gwift)gwift@gwift:~$ gunicorn gwift.wsgi:application --bind esever_name.com:8000
Et en se rendant sur server_name.com:8000/admin, on obtient la même chose qu'avec le serveur de django:
.. image:: production/admin_without_static.png
:align: center
Nous allons maintenant créer un ficheir qui se chargera de lancer gunicorn correctement, que l'on sauve dans ``/webapps/gwift/gwift/bin/gunicorn_start``:
.. code-block:: shell
#!/bin/bash
# Define settings for gunicorn
NAME="gwift" # Name of the application
DJANGODIR=/webapps/gwift/gwift/gwift # Django project directory
SOCKFILE=/webapps/gwift/gwift/run/gunicorn.sock # we will communicte using this unix socket
USER=gwift # the user to run as
GROUP=webapps # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=gwift.settings # which settings file should Django use
DJANGO_WSGI_MODULE=gwift.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
source /webapps/gwift/.virtualenvs/gwift/bin/activate
cd $DJANGODIR
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Start your Django Unicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=-
Explications:
* NUM_WORKERS : gunicorn lance autant de worker que ce nombre. Un worker représente l'équivallant d'une instance de django et ne peut traiter qu'une requête à la fois. Traditionnellement, on créé autant de worker que le double du nombre de processeurs plus un.
* SOCKFILE : on configure gunicorn pour communiquer via un socket unix, ce qui est plus efficace de le faire par tcp/ip
Le script se charge donc de définir les options de configuration de gunicorn, de lancer l'environnement virtuel et ensuite gunicorn.
On peut le tester avec la commande suivante (hors environnement virtuel):
.. code-block:: shell
gwift@gwift:~$ source /webapps/gwift/gwift/bin/gunicorn_start
Et avec un petit ``ps`` dans un autre shell:
.. code-block:: shell
gwift@gwift:~$ ps -u gwift -F
UID PID PPID C SZ RSS PSR STIME TTY TIME CMD
gwift 31983 15685 0 18319 15084 1 Apr29 ? 00:00:01 gunicorn: master [gwift]
gwift 31992 31983 0 35636 29312 1 Apr29 ? 00:00:00 gunicorn: worker [gwift]
gwift 31993 31983 0 35634 29280 2 Apr29 ? 00:00:00 gunicorn: worker [gwift]
gwift 31994 31983 0 35618 29228 0 Apr29 ? 00:00:00 gunicorn: worker [gwift]
On voit donc bien qu'il y a un maître et trois workers.

View File

@ -2,15 +2,50 @@
Monitoring
**********
Pour lancer et surveiller gunicorn, nous allons utiliser supervisord, qui est un démon sous lunix permettant de lancer d'autre programmes.
On commence par l'installer:
.. code-block:: shell
[program:simple]
command={{ virtualenv_path }}/bin/gunicorn simple.app:app -w {{ workers }} --log-file={{ appdir }}/logs/gunicorn.log --bind 127.0.0.1:{{ proxy_port }}
directory={{ appdir }}/
environment=PATH="{{ virtualenv_path }}/bin"
user=nobody
autostart=true
autorestart=true
killasgroup = true
redirect_stdout=true
redirect_stderr=true
$$$ aptitude install supervisor
On crée ensuite une fichier de configuration, ``/etc/supervisor/conf.d/gwift.conf``, qui sera lu au démarage de supervisord.
.. code-block:: shell
[program:gwift]
command = /webapps/gwift/gwift/bin/gunicorn_start ; Command to start
user = gwift ; User to run as
stdout_logfile = /webapps/gwift/gwift/logs/gunicorn_supervisor.log ; Where to write log messages
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 ; Set UTF-8 as default encoding
autostart=true ; Start the program when supervisord is starting
autorestart=unexpected ; Restart program if it exited anormaly
redirect_stdout=true ; Redirect program output to the log file
redirect_stderr=true ; Redirect program error to the log file
On peut alors démarer supervisor:
.. code-block:: shell
$$$ service supervisor start
On peut vérifier que notre site est bien en train de tourner, à l'aide de la commande ``supervisorctl``:
.. code-block:: shell
$$$ supervisorctl status gwift
gwift RUNNING pid 31983, uptime 0:01:00
Pour gérer le démarage ou l'arrêt de notre application, nous pouvons effectuer les commandes suivantes:
.. code-block:: shell
$$$ supervisorctl stop gwift
gwift: stopped
root@ks3353535:/etc/supervisor/conf.d# supervisorctl start gwift
gwift: started
root@ks3353535:/etc/supervisor/conf.d# supervisorctl restart gwift
gwift: stopped
gwift: started

View File

@ -7,6 +7,12 @@ FrontEnd
Nginx est là pour agir en tant que front-end Web. A moins d'avoir configuré un mécanisme de cache type `Varnish <https://www.varnish-cache.org/>`_, c'est lui qui va recevoir la requête envoyée par l'utilisateur, gérer les fichiers et les informations statiques, et transmettre toute la partie dynamique vers Gunicorn.
Pour l'installer, on effectue la commande suivante:
.. code-block:: shell
$$$ aptitude install nginx
L'exemple ci-dessous se compose de plusieurs grandes parties: commune (par défaut), static, uploads, racine.
Partie commune
@ -18,7 +24,7 @@ Partie commune
* keepalive ??
* La compression Gzip doit-elle être activée ?
* Avec quels paramètres ? [gzip_comp_level 7, gzip_proxied any]
* Quels types de fichiers GZip doit-il prendre en compte ? [
* Quels types de fichiers GZip doit-il prendre en compte ?
* Où les fichiers de logs doivent-ils être stockés ? [/logs/access.log & /logs/error.log]
Fichiers statiques
@ -36,13 +42,33 @@ Si vous souhaitez implémenter un mécanisme d'accès géré, supprimez cette pa
Racine
------
La partie racine de votre domaine ou sous-domaine fera simplement le *pass_through* vers l'instance Gunicorn. En gros, et comme déjà expliqué, Gunicorn tourne en local sur un port (eg. 8001); la requête qui arrive sur le port 80 ou 443 est prise en compte par NGinx, puis transmise à Gunicorn sur le port 8001. Ceci est complétement transparent pour l'utilisateur de notre application.
La partie racine de votre domaine ou sous-domaine fera simplement le *pass_through* vers l'instance Gunicorn via un socket unix. En gros, et comme déjà expliqué, Gunicorn tourne en local sur un port (eg. 8001); la requête qui arrive sur le port 80 ou 443 est prise en compte par NGinx, puis transmise à Gunicorn sur le port 8001. Ceci est complétement transparent pour l'utilisateur de notre application.
On délare un upstream pour préciser à nginx comment envoyer les requêtes à gunicorn:
.. code-block:: shell
upstream gwift_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server unix:/directory/to/gunicorn.sock fail_timeout=0;
}
Au final
--------
.. code-block:: shell
upstream gwift_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server unix:/directory/to/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
client_max_body_size 4G;
@ -58,7 +84,7 @@ Au final
error_log {{ cwd }}/logs/error.log;
location /static/ {
alias {{ static_root }}/;
alias /webapps/gwift/gwift/static;
gzip on;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
gzip_comp_level 9;
@ -80,10 +106,23 @@ Au final
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://127.0.0.1:{{ proxy_port }};
proxy_pass http://gwift_server;
}
}
Dans notre cas, et à adbater suivant les besoins, nous avans créé le fichier ``/etc/nginx/sites-available/gwift`` et créé un lien symbolique dans ``/etc/nginx/sites-enabled/gwift`` pour l'activer. Ensuite, nous pouvons redémarer nginx:
.. code-block:: shell
$$$ service nginx restart
Et maintenant, si on se connecte à notre server sur www.sever_name.com/admin, nous obtenons le site suivant:
.. image:: production/admin_with_static.png
:align: center
Où l'on peut voir que la mise en forme est correcte, ce qui signifie que les fichiers statics sont bien servis par nginx.
Modules complémentaires
=======================