Como hacer deployment de una aplicación Django:

Que tal un saludo a todos, este es mi primer articulo en <» DesdeLinux (de varios que tengo en mis borradores xD), espero les sea de utilidad 😀

Bueno, en mi nuevo y actual trabajo, en estos momentos se esta realizando la migración de varios sistemas hacia Django (que raro eh?? xD) y una de mis tareas, aparte del desarrollo, es la puesta en producción de estos, entonces como buen aprendiz, puesto que era mi primera vez poner en producción una aplicación en un servidor real :$ me puse a leer la doc oficial de cada uno de los paquetes requeridos del stack (Gunicorn y Supervisord mas que todo),  y viendo que los tutoriales en español que hay no me fueron muy claros en algunos aspectos, decidí crear una mini guía con los pasos que segui para poner en producción la aplicacion, basándonos en el stack Django, Gunicorn, Supervisord, Nginx y Postgresql.

En el caso donde trabajo, los servidores aun corren con Debian Squeeze, pero la guía debería ser totalmente valida para otras distribuciones… entonces vayamos directo al grano y comencemos:

Yo trabajare como super usuario. Primero que nada, se requieren los siguientes paquetes:

PIP -> Herramienta para instalar y administrar paquetes para Python
aptitude install python-pip

Nginx -> Servidor web (lo utilizaremos como proxy invertso y para cachear los archivos estaticos ‘img, js, css’ ) Lo instalamos con:
aptitude install nginx

Supervisord – > Aplicación para administrar y supervisar nuestra aplicación, aunque sirve para mucho mas. Lo instalamos con:
aptitude install supervisor

Virtualenv -> Nos sirve para crear un entorno virtual de ejecución personalizado para nuestra aplicación. Lo instalamos con:
aptitude install python-virtualenv

Gunicorn -> Servidor web para python (esto no lo instalaremos todavía)

Asumo que ya deberían tener instalado y configurado postgresql

psycopg2 -> Conector de postgresql para python (tampoco lo instalaremos todavia)

Crear entorno virtual con virtualenv:

Primero vamos a movernos hasta el directorio de trabajo que utilizaremos para la puesta en producción:
cd /var/www/

Luego en dicho directorio crearemos el entorno virtual:
virtualenv ENV-nombreApp

Nos movemos hasta el directorio que acabo de crear virtualenv
cd ENV-nombreAPP

Copiamos la aplicación en este directorio y ahora procedemos a activar el entorno con:
source bin/activate

El prompt deberá quedar ahora como (ENV)usuario@host:

Esto hará que ahora todo lo que hagamos este almacenado en el directorio /var/www/ENV-nombreAPP/ sin afectar los paquetes del sistema

Ahora nos movemos al directorio de la aplicación:
cd nombreApp

Procedemos a instalar la lista de dependencias de la aplicación (de ser necesario), en el cual las mismas están especificadas en el archivo requirements.txt:
pip install -r requirements.txt

También podemos instalar paquetes de manera individual, por ejemplo, para instalar el conector de postgresql:
pip install psycopg2

Instalación y configuración de GUnicorn:

Para instalarlo lo hacemos de la misma manera:
pip install gunicorn

Ahora vamos a configurarlo, para ello vamos a crear un archivo llamado gunicorn-deploy.py en la raíz de nuestra aplicación, (aunque el nombre puede ser cualquiera) con el siguiente contenido:

bind = "127.0.0.1:8001" # dirección a donde accederá Nginx
logfile = "/var/www/logs/nombreApp/gunicorn.log" # dirección donde estarán los logs de la aplicación
workers = 1 # dependerá en medida de la carga de trabajo que tenga la aplicación, también depende del hardware con que se cuente
loglevel = 'info' # tipo de logging

Configuracion de Supervisord:

Ahora configuremos el supervisord, para eso generamos el fichero de configuración con

echo_supervisord_conf > /etc/supervisord.conf

Ahora editamos el archivpo de configuración:
vim /etc/supervisord.conf

Y descomentamos las siguientes lineas quitandole el ;  (punto y coma):

[unix_http_server]
file=/tmp/supervisor.sock  

[supervisord]
logfile=/var/log/supervisord.log 
logfile_maxbytes=50MB       
logfile_backups=10         
loglevel=debug             
pidfile=/var/run/supervisord.pid 
nodaemon=false              
minfds=1024                 
minprocs=200                

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:
[program:nombreApp]
command=/var/www/ENV-nombreApp/bin/django_unicorn -c /var/www/ENV-nombreApp/nombreApp/gunicorn-deploy.py
directory=/var/www/ENV-nombreApp/nombreApp/
autostart=true
autorestart=true
user=nombreUser
redirect_stderr=true
stdout_logfile=/var/www/logs/nombreApp/supervisord.log

Ahora crearemos el script para que supervisord inicie con el sistema, para eso crearemos el archivo:
vim /etc/init.d/supervisord

Y le agregamos el siguiente contenido:

 # Supervisord auto-start
 #
 # description: Auto-starts supervisord
 # processname: supervisord
 # pidfile: /var/run/supervisord.pid

SUPERVISORD=/usr/local/bin/supervisord
SUPERVISORCTL=/usr/local/bin/supervisorctl

case $1 in
start)
        echo -n "Iniciando supervisord:"
        $SUPERVISORD
        echo
        ;;
stop)
        echo -n "Deteniendo supervisord:"
        $SUPERVISORCTL shutdown
        echo
        ;;
restart)
        echo -n "Deteniendo supervisord:"
        $SUPERVISORCTL shutdown
        echo
        echo -n "Iniciando supervisord: "
        $SUPERVISORD
        echo
        ;;
esac

Y ahora le damos permisos de ejecución al archivo para que pueda iniciar con el sistema:
sudo chmod +x /etc/init.d/supervisord

Actualizamos los enlaces para arrancar el servicio:
sudo update-rc.d supervisord defaults

Iniciamos el servicio:
sudo /etc/init.d/supervisord start

Configurando nginx:

Este paso también es bastante sencillo, crearemos el siguiente archivo de configuración de nginx para nuestra aplicación:

vim /etc/nginx/sites-enabled/nombreApp

Y le agregaremos el siguiente contenido

server {

        listen 9001; # puerto donde quieren que escuche nginx
        server_name www.dominio.com; # o 192.168.0.100, dirección a la cual accederemos
        access_log /var/log/nginx/nombreApp.access.log; # donde tendremos el log de la aplicación

        location / { # a donde llamara nginx al acceder a www.dominio.com/
                proxy_pass http://127.0.0.1:8001; 
                proxy_set_header Host $http_host;
        }

        location /static/ { # a donde accedera nginx cuando ingresemos en www.dominio.com/static/ 
                alias /var/www/ENV-nombreApp/nombreApp/staticfiles/; 
        }

}

Y reiniciamos nginx:
service nginx restart

Configurando Django:

Vamos a modificar el archivo de configuración de django:
vim nombreApp/settings.py

Buscamos la linea que dice DEBUG = True y le cambiamos el valor, quedando DEBUG = False

Agregamos los parámetros de la DB:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # o mysql, o lo que estén usando
        'NAME': 'nombreDB',
        'USER': 'usuarioDB',
        'PASSWORD': 'contrasenaDB',
        'HOST': 'localhost', # o el que necesiten
        'PORT': '', # o el que esten usando
    }
}

Buscamos la linea ALLOWED_HOSTS=[] y le agregamos el dominio o la dirección por medio del cual accederemos, quedando algo como ALLOWED_HOSTS=[‘www.dominio.com’]

Configuramos el directorio para los archivos estáticos, buscamos la linea que dice STATIC_ROOT = ' ' y le cambiamos el valor, colocándole la ruta absoluta donde queremos que estén nuestros archivos estáticos, en mi caso lo deje  mas o menos así STATIC_ROOT='/var/www/ENV-nombreApp/nombreApp/statics/'

Ya casi por finalizar, ejecutamos el siguiente comando:
./manage.py collectstatic

Esto nos creara una carpeta con el nombre ‘statics en la ruta que especificamos en el settings.py , es allí donde estarán todos nuestros archivos estáticos.

Y por ultimo reiniciamos el supervisord para que tome los nuevos cambios:
supervisorctl restart nombreApp

Y eso seria todo, al final no era para tanto verdad? a mi me pareció sencillo 😀

Espero les sea de utilidad, saludos 😉

Documentación GUnicorn

Documentación Supervisord


Deja tu comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

  1. Responsable de los datos: Miguel Ángel Gatón
  2. Finalidad de los datos: Controlar el SPAM, gestión de comentarios.
  3. Legitimación: Tu consentimiento
  4. Comunicación de los datos: No se comunicarán los datos a terceros salvo por obligación legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu información.

      F3niX dijo

    Tengo entendido que no se debería poner la app Django en la raiz de la carpeta del servidor web(/var/www)? por seguridad, no se si me equivoco.

    Saludos.

         urKh dijo

      Toda la razón!!! era algo que desconocía totalmente, actualizare la entrada 😛 y apenas regrese el lunes haré cambios en la aplicación xD
      Gracias

      Rodrigo Bravo (goidor) dijo

    Epale hermano buen tutorial. Hace poco también estuve en lo mismo pero en Debian 7, tuve que buscar y leer mas o menos. Te recomiendo que el entorno virtual del virtualenv lo crees en el home del usuario en una carpeta oculta.

    Saludos!

      Serv Fenriz dijo

    jajaja ctm yo ayer documentandome de Django y vos ya vais por la galaxia 999999 Saludos men xD

      daniel2ac dijo

    Muy buen articulo =) apenas hace una semana hice el deploy de mi app de django pero lo hice con uwsgi y nginx, sabes que ventaja tiene gunicorn? he visto que lo mencionan mucho.
    Da gusto ver que se esta popularizando mucho django, la verdad es el mejor framework que he visto =)

      Ozkar dijo

    Para el STATIC_ROOT lo que hago es definir una variable global. Algo como esto:

    import os
    PROJECT_PATH = os.path.dirname(os.path.abspath(__file__))
    STATIC_ROOT = os.path.join(PROJECT_PATH, '../backend/static')

    Donde backend es una app que yo creé. Asi me aseguro que donde despliegue el proyecto, la ruta global sea la misma.

      sgmart dijo

    Interesante, lo intentaré en lo sucesivo.

    A propósito, alguien sabe ¿Cómo habilitar los acentos y caracteres no ascii en una aplicación django?

    He buscado por todos lados, ninguna de los siguientes métodos me funcionan:
    sys.setdefaultencoding(‘utf-8’) # en sites.py

    # -*- coding: utf-8 -*- # en cada archivo python

    Se supone que al editar site.py, y colocar utf-8 en vez de ascii debería funcionar, pero $ file models.py me informa que mi archivo sigue siendo un ascii.

    ¿Alguna Sugerencia?

         sgmart dijo

      Ya funcionó!!!!

      anime230 dijo

    muy buen tutortial pero podrias hacer uno de como subir mi app en un servidor web ya en produccion
    gracias