lunes, 25 de noviembre de 2013

Puesta en producción de una aplicación web con Django y Nginx


Cuando se usan frameworks para desarrollo web todo se hace más fácil, excepto la puesta en producción, una muestra clara de esto es django, un framework que permite que cosas como hacer un entorno de administración parezca juego de niños y que realizar consultas que parecen concebidas en la maligna mente del mismo Satanás sea una tarde de picnic. Desafortunadamente a la hora de poner en producción un proyecto empezamos a ver dificultades. Este post tiene como objetivo mostrar una sencilla manera de poner en producción nuestros proyectos con Django mediante el servidor Nginx.

Nota: Todo el proceso de configuración esta preparado para Linux Debian y derivados, si usas una distribución diferente es probable que cambien las rutas de los archivos de configuración.

Primero que todo, ¿Qué es Nginx?

Nginx es un servidor web y proxy inverso ligero de muy alto rendimiento, es software libre de código abierto y multiplataforma, tiene las siguientes características:
  • Servidor de archivos estáticos, índices y autoindexado.
  • Proxy inverso con opciones de caché.
  • Permite realizar balanceo de carga.
  • Tolerancia a fallos.
  • Soporte de HTTP sobre SSL.
  • Soporte para FastCGI con opciones de caché.
  • Servidores virtuales basados en nombre y/o en dirección IP.
  • Streaming de archivos FLV y MP4.
  • Soporte para autenticación.
  • Compatible con IPv6.
  • Soporte para protocolo SPDY.
  • Soporte para compresión gzip de paquetes.
  • Habilitado para soportar más de 10.000 conexiones simultáneas.
Muy bien, pero ¿Qué pasa con lo clásico?
Muchos se preguntaran ¿Por qué Nginx y no Apache2?, pienso que hay varias cosas al respecto:
  • La cantidad de recursos que demanda Apache2 son mucho mayores que los demandados por Nginx.
  • La velocidad alcanzada por Nginx es mucho mayor que la de Apache2 a la hora de responder peticiones.
  • Nginx es muchisimo más fácil de configurar que Apache2 puesto que Apache2 usa engorrosos XMLs, Nginx no.
La información mencionada la obtuve de aquí, aquí y aquí.

Muy bien, entonces, manos a la obra
En este momento me parece adecuado explicar cómo funciona la conexión entre django y Nginx:

Nginx es el encargado de atender las peticiones externas por el puerto 80 (protocolo HTTP), éste a su vez envía los datos de la petición a uWSGI mediante un puerto auxiliar, quien hace de intermediario en el proceso de comunicación y finalmente uWSGI entrega los datos de petición a nuestro proyecto django para que éste ejecute la acción correspondiente e inicie el proceso inverso para responder a la petición. Escogí uWSGI porque me pareció muy fácil de usar y en éste enlace hay una comparativa de rendimiento en la cual el tiempo de respuesta es mejor que el de Gunicorn.

Configuremos Nginx
Debemos crear el archivo de configuración para nuestro proyecto, recuerda que si el puerto 80 está siendo usado por Apache2, por alguna otra aplicación o por el mismo Nginx por otra configuración debes liberar primero el puerto, en caso de ser Apache2 debes editar el archivo /etc/apache2/ports.conf y cambiar el puerto 80 por uno diferente, luego reiniciar el servicio Apache2 así:
$ service apache2 restart
Después de esto debes crear el archivo de configuración en la carpeta /etc/nginx/sites-avaliable, el nombre del archivo lo eliges tú, yo elegí como nombre archivo.conf. El contenido del archivo debe ser el siguiente:
# archivo.conf
server {
    listen      80; # puerto por el que escucha la aplicación
    server_name midominio.co; # nombre o ip del servidor
    charset     utf-8;

    # tamaño maximo de subida
    client_max_body_size 75M;

    # Ruta de la carpeta media
    location /media  {
        alias /var/www/proyecto/media; # reemplace por su ruta a media
    }

    # Ruta de la carpeta static
    location /static {
        alias /var/www/proyecto/static; # reemplace por su ruta a media
    }

    # Configuración de las peticiones que no son resueltas con las
    # reglas anteriores. Estas son reenviadas al servidor django
    location / {
        uwsgi_pass 127.0.0.1:8001; # 127.0.0.1:PUERTO_AUXILIAR
        include     uwsgi_params;
    }
}
Cabe resaltar que el puerto auxiliar seleccionado es el 8001, este dato es importante puesto que debemos tenerlo en cuenta para iniciar la labor de uWSGI.
Después de esto es necesario habilitar la nueva configuración creando un enlace simbólico del archivo en la carpeta sites-avaliable de Nginx así:
$ cd /etc/nginx/sites-enabled
$ ln -s ../sites-avaliable/archivo.conf .
Finalmente reiniciamos el servidor Nginx
$ service nginx restart

Configuremos nuestro entorno
Primero es necesario crear un entorno para el proyecto con la orden mkvirtualenv vista en el post anterior y luego activamos el entorno creado con la orden workon:
$ mkvirtualenv entorno
$ workon entorno
después de ésto es necesario instalar las dependencias de nuestro proyecto django, personalmente pienso que es bueno trabajar con django 1.5 o superior, puesto que aasi tendremos muchas de las nuevas características, además django 1.6 fue liberado hace un par de semanas.
$ pip install django
$ pip install ....
$ pip install ....
Ahora necesitamos instalar uWSGI:
$ pip install uwsgi
Nota: Para instalar uWSGI es necesario tener instalados en el sistema el compilador gcc y los paquetes de desarrollo de python, para el caso de linux debian y derivados con python2.7 deben instalarse como superusuario así:
$ apt-get install gcc-4.5 python2.7-dev
Finalmente creamos el archivo para iniciar el proceso de conexión entre Nginx y django, este archivo es un script bash al que yo llame start.sh, este debe tener el siguiente contenido:
#!/bin/bash
uwsgi --socket :8001 --wsgi-file wsgi.py -d mensajes.log

Aquí viene la parte importante, cuando django genera un proyecto él crea una carpeta de proyecto, dentro de ésta hay una carpeta con los archivos de configuración, éstos son settings.py, urls.py, __init__.py y wsgi.py


debe hacer una copia del archivo wsgi.py a la raíz del proyecto y en éste mismo lugar poner el archivo start.sh así:

Después es necesario permitir la ejecución de este archivo mediante la orden:
$ chmod +x start.sh
Luego podemos iniciar el proceso así:
$ ./start.sh
Si tienes alguna duda o comentario puedes hacerla en la sección de comentarios, espero que sea útil.

Si te gusto el post
compartelo... :D

No hay comentarios:

Publicar un comentario