Update production
This commit is contained in:
parent
c22dfe89fd
commit
8bb5ec1730
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
|
@ -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
|
||||
====
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
=======================
|
||||
|
||||
|
|
Loading…
Reference in New Issue