Crear un proxecto Django nun servidor privado
Escrito por [email protected] o
Creamos unha base de datos para a app (hello):
Neste caso, eleximos postgreSQL
$ sudo aptitude install postgresql postgresql-contrib
$ sudo su - postgres
[email protected]:~$ createuser --interactive -P
Enter name of role to add: hello
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
[email protected]:~$
[email protected]:~$ createdb --owner hello_django hello
[email protected]:~$ logout
Creamos o noso usuario
$ sudo groupadd --system hello_group # nome do grupo
$ sudo useradd --system --gid hello_group --shell /bin/bash --home /webapps/hello_django hello
Virtualenv
Instalamos o virtualenv se fose necesario, senon simplemente creamos o entorno virtual.
Para instalar virtualenv
$ sudo aptitude install python-virtualenv
Antes de crear o noso entorno virtual, creamos o path do proxecto
$ sudo mkdir -p /webapps/hello_django/
$ sudo chown hello /webapps/hello_django/
Identificamonos có usuario creado e lanzamos o comando de creación do entorno virtual, a opción '-p' usámola para poder indicar a versión de python
$ sudo su - hello
[email protected]:~$ cd /webapps/hello_django/
[email protected]:~$ virtualenv -p /usr/bin/python3.6 .
New python executable in hello_django/bin/python
Installing distribute..............done.
Installing pip.....................done.
[email protected]:~$ source bin/activate
(hello_django)[email protected]:~$
Una vez lcheegados a este punto, continuamos coa configuración do servidor, dandolle os permisos necesarios as carpetas
$ sudo chown -R hello:hello_group /webapps/hello_django
$ sudo chmod -R g+w /webapps/hello_django
Gunicorn
Para executar a nosa aplicación django en producción, utilizaremos Gunicorn. É necesario instalar gunicorn no entorno virtual do proxecto:
(hello_django)[email protected]:~$ pip install gunicorn
Downloading/unpacking gunicorn
Downloading gunicorn-0.17.4.tar.gz (372Kb): 372Kb downloaded
Running setup.py egg_info for package gunicorn
Installing collected packages: gunicorn
Running setup.py install for gunicorn
Installing gunicorn_paster script to /webapps/hello_django/bin
Installing gunicorn script to /webapps/hello_django/bin
Installing gunicorn_django script to /webapps/hello_django/bin
Successfully installed gunicorn
Cleaning up...
Para arrancar unha aplicación Django con gunicorn:
(hello_django)[email protected]:~$ gunicorn hello.wsgi:application --bind dominio.com:8001
Neste caso no porto 8001.
Agora vamos a crear un ficheiro 'bin/gunicorn_start' para utilizalo para iniciar a app
#!/bin/bash
NAME="hello_django_app" # Name of the application
DJANGODIR=/webapps/hello_django/src/hello_django # Django project directory
SOCKFILE=/webapps/hello_django/run/gunicorn.sock # we will communicte using this unix socket
USER=hello_django # the user to run as
GROUP=hello_group # the group to run as
NUM_WORKERS=5 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=hello_django.settings # which settings file should Django use
DJANGO_WSGI_MODULE=hello_django.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
source /webapps/hello_django/bin/activate
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 /webapps/hello_django/bin/gunicorn \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--timeout=120 \
--log-level=info \
--log-file=- \
${DJANGO_WSGI_MODULE}:application
Este ficheiro debe ter permisos de execución:
$ sudo chmod u+x bin/gunicorn_start
Pódese probar que esta correcto, da seguinte maneira:
$ sudo su - hello
[email protected]:~$ bin/gunicorn_start
Starting hello_app as hello
2013-06-09 14:21:45 [10724] [INFO] Starting gunicorn 18.0
2013-06-09 14:21:45 [10724] [DEBUG] Arbiter booted
2013-06-09 14:21:45 [10724] [INFO] Listening at: unix:/webapps/hello_django/run/gunicorn.sock (10724)
2013-06-09 14:21:45 [10724] [INFO] Using worker: sync
2013-06-09 14:21:45 [10735] [INFO] Booting worker with pid: 10735
2013-06-09 14:21:45 [10736] [INFO] Booting worker with pid: 10736
2013-06-09 14:21:45 [10737] [INFO] Booting worker with pid: 10737
^C (CONTROL-C to kill Gunicorn)
Formula para calcular os --workers (NUM_WORKERS): 2 * CPUs + 1.
Supervisor
$ sudo aptitude install supervisor
Unha vez instalado supervisor, debemos crear o ficheiro de configuración:
[program:hello]
command = /webapps/hello_django/bin/gunicorn_start ; Command to start app
user = hello ; User to run as
stdout_logfile = /webapps/hello_django/logs/gunicorn_supervisor.log ; Where to write log messages
redirect_stderr = true ; Save stderr in the same log
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 ; Set UTF-8 as default encoding
Crearémos un ficheiro para almacenar os mensaxes de log:
[email protected]:~$ mkdir -p /webapps/hello_django/logs/
[email protected]:~$ touch /webapps/hello_django/logs/gunicorn_supervisor.log
Logo é necesario gardar a configuración e engadir a app a supervisor
$ sudo supervisorctl reread
hello: available
$ sudo supervisorctl update
hello: added process group
Algún comandos de supervisor interesantes:
$ sudo supervisorctl status
hello hello RUNNING pid 18020, uptime 0:00:50
$ sudo supervisorctl stop hello
hello: stopped
$ sudo supervisorctl start hello
hello: started
$ sudo supervisorctl restart hello
hello: stopped
hello: started
Nginx
$ sudo aptitude install nginx
$ sudo service nginx start
Crearemos o ficheiro de configuración /etc/nginx/sites-available/hello da siguinte maneira:
upstream hello_django_app_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:/webapps/hello_django/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name hello_django.dominio.com;
client_max_body_size 4G;
access_log off; #/webapps/hello_django/logs/nginx-access.log;
error_log /webapps/hello_django/logs/nginx-error.log;
location /static/ {
alias /webapps/hello_django/src/hello/static/;
expires 365d;
}
location /media/ {
alias /webapps/hello_django/src/media/;
expires 365d;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
#proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://hello_django_app_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /error.html {
root /webapps/hello_django/src/hello_django/templates/;
}
# Compression
# Enable Gzip compressed.
gzip on;
# Enable compression both for HTTP/1.0 and HTTP/1.1.
gzip_http_version 1.1;
# Compression level (1-9).
# 5 is a perfect compromise between size and cpu usage, offering about
# 75% reduction for most ascii files (almost identical to level 9).
gzip_comp_level 5;
# Don't compress anything that's already small and unlikely to shrink much
# if at all (the default is 20 bytes, which is bad as that usually leads to
# larger files after gzipping).
gzip_min_length 256;
# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
gzip_proxied any;
# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
gzip_vary on;
# Compress all output labeled with one of the following MIME-types.
gzip_types
application/atom+xml
application/javascript
application/x-javascript
application/json
application/js
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/javascript
text/xml
text/x-component;
}
Un enlace para activar o sitio:
$ sudo ln -s /etc/nginx/sites-available/hello /etc/nginx/sites-enabled/hello
Por último reiniciamos Nginx:
$ sudo service nginx restart
Se todo saíu ben, deberíamos ter o sitio funcionando no noso servidor de producción