¿Cómo llevar Django a producción?

Curso Básico de Python

Toma las primeras clases gratis

COMPARTE ESTE ARTÍCULO Y MUESTRA LO QUE APRENDISTE

Uno de los aspectos más importantes en el ciclo de vida de cualquier aplicación web es llevarla a producción. Es una parte fundamental y en algunas ocasiones poco documentada por la gran cantidad de configuraciones posibles que existen.

Django es un framework para desarrollo web pero hay muy poca información relacionada sobre como hacer despliegue o deploy (en ingles). Voy a explicar cómo llevar a producción una aplicación hecha en Django usando** Nginx** como servidor web y una base de datos PostgreSQL.

Siguiendo estos pasos se pueden hacer despliegues sin problema en AWS, Digital Ocean o cualquier otro servicio de VPS con algunos cambios dependiendo de la infraestructura.

Para hacer un deploy de Django por su estructura es necesario que se tenga acceso via ssh por lo cual es muy difícil que un hosting compartido tenga soporte para hacer despliegue de estas aplicaciones.

En este despliegue, vamos a usar Ubuntu server 16.04, la última versión LTS. Si no tienes conocimientos sobre administración es recomendable que tomes el curso de administración de servidores linux y el curso de introducción a la terminal y línea de comandos.

Actualizar el servidor

Una vez tenemos nuestro servidor corriendo y estamos en la terminal, procedemos a actualizar el servidor e instalar los paquetes necesarios para realizar el despliegue ejecutando los siguientes comandos:

sudo apt-get update
sudo apt-get upgrade

Instalando paquetes necesarios

Luego vamos a instalar Nginx, PostgreSQL, Git y Supervisor, como se mencionó Nginx es nuestro servidor web, PostgreSQL es nuestro motor de base de datos y Supervisor va a ser el encargado de mantener nuestro servicio de la aplicación corriendo y si llega a fallar iniciar nuevamente el servicio de forma automática. Git nos permite conectarnos al repositorio remoto y traer nuestra aplicación desarrollada en Django.

¿Qué es y para que sirve Git?

sudo apt-get install nginx postgresql postgresql-contrib supervisor

Ya tenemos lo básico instalado para iniciar nuestro despliegue en el servidor, adicional a esto necesitamos instalar un par de cosas como es un entorno virtual y gunicorn. Gunicorn es un servidor de aplicaciones que nos permite conectar por medio de sockets nuestra aplicación Django con Nginx para que pueda ser utilizada.

Instalamos virtualenvwrapper (es mi recomendación personal)

sudo pip install virtualenvwrapper

Creando el entorno virtual

Creamos un entorno virtual usando Python 3 como versión de entorno virtual

mkvirtualenv miapp --python=$(which python3)

Para verificar que estamos en el entorno virtual

workon miapp

Usando Git para traer nuestro proyecto

Vamos a traer nuestro código del repositorio remoto para esto procedemos a crear una carpeta para guardar el código en la carpeta de nuestro usuario, Es recomendable no usar nunca el usuario root como usuario principal ya que tiene implicaciones de seguridad vamos a la carpeta del usuario y creamos una carpeta llamada myapp y nos movemos a la carpeta.

cd ~
mkdir myapp
cd myapp

Traemos nuestro repositorio usando git

git clone <url repo>

Instalando las dependencias de la aplicación

Algo muy importante es instalar todos las dependencias de nuestro proyecto en el entorno virtual, par esto vamos a ejecutar

pip install -r <path requirements.txt>

Configurando PostgreSQL

Vamos a configurar el motor de PostgreSql. Si quieres aprender más sobre la administración de PostgreSQL te recomiendo el curso de PostgreSQL

A continuación cremos un user llamado myapp sin permisos de superusuario sin capacidad de crear bases de datos. Sólo le vamos a asignar una base de datos también llamada myappdb para que pueda usarla este usuario

$ sudo su - postgres
postgres@server:~$ createuser --interactive -P
Enter name of role to add: myapp
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
postgres@server:~$

postgres@server:~$ createdb --owner myapp myappdb
postgres@server:~$ logout
No olvides cambiar los settings de tu aplicación de django para conectarse a la base de datos con la información que acabas de usar para poder conectar de manera correcta la aplicación a la base de datos.

Una vez realizado los cambios puedes correr el comando para ejecutar las migraciones.

cd ~/myapp
./manage.py migrate

Configurando Gunicorn

En este punto creamos un script llamado start.sh dentro de una carpeta llamada bin que va a estar dentro de nuestro directorio que creamos al clonar el repositorio, el script está comentado explicando que hace cada linea

#!/bin/bash

NAME="myapp" # Nombre de la aplicación
DJANGODIR=/home/<user>/myapp # Ruta de la carpeta donde esta la aplicación reemplazar <user> con el nombre de usuario
SOCKFILE=/home/<user>/run/gunicorn.sock # Ruta donde se creará el archivo de socket unix para comunicarnos
USER=<user> # Usuario con el que vamos a correr la app
GROUP=<groupe> # Grupo con el que se va a correr la app
NUM_WORKERS=3 # Número de workers que se van a utilizar para correr la aplicación
DJANGO_SETTINGS_MODULE=myapp.settings # ruta de los settings
DJANGO_WSGI_MODULE=myap.wsgi # Nombre del módulo wsgi

echo "Starting $NAME as `whoami`"

# Activar el entorno virtual
cd $DJANGODIR
workon miapp 
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

# Crear la carpeta run si no existe para guardar el socket linux
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

# Iniciar la aplicación django por medio de gunicorn
exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE \
  --log-level=debug \
  --log-file=-

Este script nos permite levantar nuestra aplicación django sin usar ./manage runserver

Algo muy importante es permitir la ejecución del archivo para esto escribimos

cd ~/myapp/bin
chmod +x start.sh 

Configurando Supervisor

Llegamos al punto de configurar supervisor, este nos va a ayudar a mantener nuestra aplicación de django corriendo, la configuración es relativamente sencilla y es un script con extensión .conf que debemos ubicar en /etc/supervisor/conf.d/

Para esto podemos usar vim, nano o cualquier editor que se tenga en la terminal, primero creamos el archivo usando sudo

sudo touch /etc/supervisor/conf.d/myapp.conf

Abrimos y copiamos el siguiente código

[program:myapp]
command = /home/<user>/bin/start.sh ; Comando para iniciar la app
user = <user> ; El usuario con el que vamos a correr la app
stdout_logfile = /home/<user>/myapp/logs/gunicorn_supervisor.log ; Donde vamos a guardar los logs
redirect_stderr = true ; Guardar los errores en el log

Recuerden cambiar <user> por el nombre del usuario en su servidor y algo muy importante crear la carpeta logs dentro de la carpeta de la app

mkdir -p /home/<user>/myapp/logs

Ahora tenemos que decirle a supervisor que lea las nuevas configuraciones y que se actualice

sudo supervisorctl reread
sudo supervisorctl update

Con supervisor podemos también mirar el estado de la aplicación, pararla, iniciarla o reiniciarla.

sudo supervisorctl status myapp                       
sudo supervisorctl stop myapp  
sudo supervisorctl restart myapp 
sudo supervisorctl start myapp

Configurando Nginx

Estamos en el último paso: configurar el servidor web para que se conecte con el socket que tenemos corriendo gracias a gunicorn y muestre nuestro sitio web.

Nginx es realmente sencillo de configurar, nginx cuenta con dos carpetas una donde se almacenan las configuraciones de los sitios disponibles y otra donde se almacenan los sitios activos, vamos a crear nuestra configuración en la carpeta /etc/nginx/sites-available creamos nuestro archivo igual a como creamos el archivo de configuración para supervisor

sudo touch /etc/nginx/sites-available/myapp.conf

Paso seguido procedemos a editarlo

upstream myapp_server {
  server unix:/home/<user>/myapp/run/gunicorn.sock fail_timeout=0;
}

server {

  listen 80;
  server_name example.com;

  client_max_body_size 4G;

  access_log /home/<user>/myapp/logs/nginx-access.log;
  error_log /home/<user>/myapp/logs/nginx-error.log;

  location /static/ {
  alias /home/<user>/myapp/static/;
  }

  location /media/ {
  alias /home/<user>/myapp/media/;
  }

  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://myapp_server;
  break;
  }
  }
}

Como en los anteriores casos reemplaza <user> por el usuario y example.com por el dominio que tengas.

Una vez hecho esto tenemos que dar de alta nuestra configuración de nuestro sitio, para esto simplemente escribimos este comando

sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/myapp.conf

Algo que hago yo es correr nginx con mi usuario para no tener problemas de permisos de escritura a la hora de hacer por ejemplo subida de archivos desde la aplicación de Django, para esto editamos el archivo nginx.conf

sudo vim /etc/nginx/nginx.conf

Si no tienes vim puedes usar nano o el editor que uses desde la terminal

y cambiamos la linea

user <user>;

Ahora solo falta reiniciar nginx

sudo service nginx restart

Ya llevaste a producción tu aplicación de Django

Llevar a producción una aplicación es la culminación del desarrollo y mostrar al mundo lo que hiciste, puede tener múltiples cambios dependiendo del servidor pero esto aplica para la mayoría de casos.

Si quieres aprender a aplicar estas técnicas y muchas más, te recomendamos visitar nuestros cursos en desarrollo web.

Curso Básico de Python

Toma las primeras clases gratis

COMPARTE ESTE ARTÍCULO Y MUESTRA LO QUE APRENDISTE

0 Comentarios

para escribir tu comentario

Artículos relacionados