Nombre: | Tutorial #3 - Cómo desplegar una aplicación Flask |
Duración: | 45 minutos |
Profesor responsable | Harold Castro, Mario Villamizar |
Pre-Requisitos: | Shell GNU/Linux, Git, Postman |
Al finalizar el tutorial el estudiante estará en capacidad de:
En particular se utilizarán los siguientes recursos:
Para administrar este proyecto usando Python 3.x, debe crear un nuevo ambiente virtual y una nueva carpeta ejecutando:
$ python3 -m venv lab-flask
Una instalación de Python 3.x es creada de inmediato en la carpeta ambiente. Para activar en nuevo entorno virtual, utilice el comando source:
$ source lab-flask/bin/activate
Para cerrar el ambiente de ejecución, ejecute el comando deactivate:
$ deactivate
La aplicación que se utilizara en este tutorial ya está desarrollada, utilizando Flask. Es un API RESTful, que expone un par de servicios para cifrar y descifrar información con el algoritmo RC4.
Clone el repositorio presentado a continuación:
$ git clone
https://github.com/jpadillaa/taller-api-flask-2.git
Para el tutorial necesitamos instalar las siguientes dependencias que están disponibles en el Python Package Index (PyPI), y para instalarlas basta con utilizar pip:
$ pip3 install flask
$ pip3 install flask-restful
$ pip3 install flask-marshmallow
Vamos a realizar un primer despliegue de la aplicación en un ambiente de desarrollo. Para esto, vamos a ingresar al directorio de la aplicación y establecer las variables de entorno de la aplicación:
$ cd taller-api-flask-2
$ export FLASK_APP=app.py
$ export FLASK_DEBUG=1
$ export FLASK_ENV=development
Como puede observar las variables especifican qué aplicación deseamos desplegar y especificamos que el ambiente es desarrollo. Para ejecutar la aplicación, escriba el siguiente comando:
$ flask run -h 0.0.0.0
El comando anterior especifica que la aplicación recibirá solicitudes sobre cualquiera de las direcciones IP que tenga asignada la máquina. Si no tiene clara la dirección IP de su máquina ejecute previamente el comando:
$ ip a
Deberá observar una consola similar a la siguiente:
En este punto la aplicación ya acepta solicitudes. Como se mencionó previamente esta aplicación ofrece dos servicios cifrar y descifrar información utilizando el algoritmo RC4. La api está compuesta por las siguientes rutas:
El endpoint 1 del API REST es el responsable de cifrar un mensaje, para esto es necesario entregarle un documento JSON con el mensaje y la respectiva llave para realizar el cifrado. Este objeto debe ser enviado a través de una solicitud POST; para esto utilice POSTMAN como se presenta a continuación:
Como puede observar en la imagen, los campos numerados corresponden a:
El endpoint 2 del API REST es el responsable de descifrar un mensaje, para esto es necesario entregarle un documento JSON con el mensaje cifrado y la respectiva llave para realizar el descifrado. Este objeto debe ser enviado a través de una solicitud POST; para esto utilice POSTMAN como se presenta a continuación:
Como puede observar en la imagen, los campos numerados corresponden a:
En esta sección del tutorial se aborda la configuración del servidor de aplicaciones Gunicorn y la forma de iniciar la aplicación Cipher, además de configurar Nginx para que funcione como un proxy inverso de cliente.
Primero, instalaremos wheel, un paquete estándar para la distribución de aplicaciones Python. El paquete se instala con pip:
$ pip3 install wheel
A continuación, instale Gunicorn en su ambiente virtual activo:
$ pip3 install gunicorn
A continuación, crearemos un archivo que servirá como punto de entrada WSGI para nuestra aplicación. Esto indicará a nuestro servidor de Gunicorn cómo interactuar con la aplicación.
Cree un nuevo archivo llamado wsgi.py y anexe el siguiente código:
from app import app if __name__ == "__main__": app.run()
En este archivo se importa la instancia de la aplicación Flask. Guarde y cierre el archivo. Antes de continuar, debe comprobar que Gunicorn pueda proveer correctamente la aplicación. Debe especificar la dirección IP y el puerto puerto de escucha Gunicorn. Ejecute el comando:
$ sudo ufw allow 5000
$ gunicorn --bind 0.0.0.0:5000 wsgi:app
Si la ejecución es correcta podrá observar una consola similar a la presentada en la siguiente imagen.
Cuando confirme que Gunicorm funciona correctamente, presione Ctrl + C en la consola. Ya desarrollada estas tareas en el entorno virtual, es necesario desactivarlo:
$ deactivate
Se debe crear un archivo de servicio systemd. Crear un archivo de servicio systemd permitirá que Ubuntu inicie automáticamente Gunicorn con la aplicación de Flask cuando el servidor inicio.
Cree un archivo con extension .service dentro del directorio /etc/systemd/system:
$ sudo nano /etc/systemd/system/app.service
Inicie describiendo la sección [Unit] que se usa para especificar metadatos y dependencias. Aquí agregaremos una descripción del API REST y se indica al sistema que lo inicie después de que el sistema operativo alcanzó el objetivo de red:
[Unit] Description=Gunicorn instance to serve APP After=network.target
Agregue la sección [Service]. Esto especificará el usuario y el grupo que ejecutan el proceso. Asigne la propiedad del proceso a la cuenta de usuario normal, ya que tiene la propiedad de todos los archivos pertinentes (para este ejemplo el usuario local se llama "ubuntu"). Asigne la propiedad del grupo al grupo www-data para que Nginx pueda comunicarse con los procesos de Gunicorn:
[Unit] Description=Gunicorn instance to serve APP After=network.target [Service] User=ubuntu Group=ubuntu
Es necesario configurar la variable PATH para que el sistema conozca los ejecutables ubicados dentro de nuestro entorno virtual. Nuestra configuración incluye:
No se olvide de sustituir el nombre del usuario y las rutas del proyecto que tenga en uso.
[Unit] Description=Gunicorn instance to serve APP After=network.target [Service] User=ubuntu Group=ubuntu WorkingDirectory=/home/ubuntu/taller-api-flask-2 Environment="PATH=/home/ubuntu/lab-flask/bin/" ExecStart=/home/ubuntu/lab-flask/bin/gunicorn --workers 1 --bind unix:app.sock -m 007 wsgi:app
Finalmente, agregue la sección [Install]. Esto asigna a systemd que debe vincular este servicio para que se cargue en el arranque:
[Unit] Description=Gunicorn instance to serve APP After=network.target [Service] User=ubuntu Group=ubuntu WorkingDirectory=/home/ubuntu/taller-api-flask-2 Environment="PATH=/home/ubuntu/lab-flask/bin/" ExecStart=/home/ubuntu/lab-flask/bin/gunicorn --workers 1 --bind unix:app.sock -m 007 wsgi:app [Install] WantedBy=multi-user.target
El archivo de servicio de systemd está completo, guarde y cierre. Inicie el servicio Gunicorn creado y actívelo para que se cargue en el arranque:
$ sudo systemctl start app
$ sudo systemctl enable app
Si la configuración es correcta, la consola le presentará un mensaje igual a este:
Created symlink /etc/systemd/system/multi-user.target.wants/app.service → /etc/systemd/system/app.service.
Verifique el estado del proceso con el comando (Cierre con q):
$ sudo systemctl status app
Si detecta errores revise los pasos anteriores. Gunicorn está configurado, escuchando solicitudes en el archivo de socket del proyecto. Ahora es necesario configurar Nginx para que transmita las solicitudes web al socket. Instale Nginx:
$ sudo apt install nginx
Verifique el firewall de Ubuntu y habilite el puerto de escucha de Nginx para solicitudes HTTP:
$ sudo ufw app list
$ sudo ufw allow 'Nginx HTTP'
Verifique que Nginx este activo (Cierre con q):
$ sudo systemctl status nginx
Cree un nuevo archivo de configuración en el directorio sites-available de Nginx, llamado app para que se adecue al resto de esta guía:
$ sudo nano /etc/nginx/sites-available/app
server { listen 80; server_name ip_servidor; location / { include proxy_params; proxy_pass http://unix:/home/ubuntu/taller-api-flask-2/app.sock; } }
Guarde y cierre el al finalizar. Habilite la configuración de Nginx que acaba de crear, vincule el archivo al directorio sites-enabled:
$ sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled
Con el archivo en ese directorio, puede realizar una verificación en busca de errores de sintaxis:
$ sudo nginx -t
Si no se indican problemas, reinicie el proceso de Nginx para que lea la nueva configuración:
$ sudo systemctl restart nginx
Ya no se requiere acceso a través del puerto 5000, por lo que debe eliminar esta regla. Luego, podemos permitir el acceso completo al servidor de Nginx:
$ sudo ufw delete allow 5000
$ sudo ufw allow 'Nginx Full'
Acceda a la aplicación vía POSTMAN y realice las pruebas respectivas. Ya no es necesario especificar el puerto.
Si encuentra algún error, verifique los logs:
$ sudo less /var/log/nginx/error.log
$ sudo less /var/log/nginx/access.log
$ sudo journalctl -u nginx
$ sudo journalctl -u app
[1] Gunicorn Docs - https://gunicorn.org/#docs
[2] Nginx - https://www.nginx.com/blog/maximizing-python-performance-with-nginx-parti-web-serving-and-caching/