Cómo desplegar una aplicación Flask con uWSGI y Nginx en Ubuntu 20.04

Flask es un microframework web escrito en Python desarrollado por Armin Ronacher. Se llama microframework porque no requiere ninguna herramienta ni biblioteca. Flask es un módulo de Python y tiene un núcleo pequeño y fácil de extender que te ayuda a desarrollar aplicaciones web fácilmente.

En este tutorial, aprenderemos a desplegar una aplicación Flask con Uwsgi y Nginx en Ubuntu 20.04.

Requisitos previos

  • Un servidor con Ubuntu 20.04.
  • Un nombre de dominio válido apuntado con la IP de tu servidor.
  • Una contraseña de root está configurado el servidor.

Cómo empezar

En primer lugar, se recomienda actualizar los paquetes de tu sistema con la última versión. Puedes actualizarlos ejecutando el siguiente comando:

apt-get update -y

Una vez actualizados todos los paquetes, puedes pasar al siguiente paso.

Instalar las dependencias necesarias

A continuación, tendrás que instalar algunas dependencias necesarias para desplegar la aplicación flask. Puedes instalarlas todas con el siguiente comando:

apt-get install nginx python3-pip python3-dev python3-venv build-essential libssl-dev libffi-dev python3-setuptools -y

Una vez instalados todos los paquetes, puedes proceder al siguiente paso.

Crear un entorno virtual

A continuación, tendrás que crear un entorno virtual para tu aplicación Flask. El entorno virtual es una herramienta muy útil para crear entornos Python aislados. Te ayuda a instalar una versión específica de Python para tu proyecto.

En primer lugar, crea un directorio para tu aplicación Flask con el siguiente comando:

mkdir /var/www/html/myapp

A continuación, cambia el directorio a myapp y crea un nuevo entorno virtual Python con el siguiente comando:

cd /var/www/html/myapp
python3.8 -m venv myappenv

A continuación, activa el entorno virtual con el siguiente comando:

source myappenv/bin/activate

Configurar una aplicación Flask

En este punto, el entorno virtual Python está listo para desplegar la aplicación Flask. A continuación, tendrás que configurar una aplicación Flask dentro de tu entorno virtual.

En primer lugar, instala Flask y uWSGI con el siguiente comando:

pip install uwsgi flask

A continuación, crea una aplicación de ejemplo llamada myapp.py con el siguiente comando:

nano /var/www/html/myapp/myapp.py

Añade las siguientes líneas:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hi This is My Flask Application</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

Guarda y cierra el archivo cuando hayas terminado. A continuación, ejecuta tu aplicación Flask con el siguiente comando:

python /var/www/html/myapp/myapp.py

Deberías ver la siguiente salida:

 * Serving Flask app "myapp" (lazy loading)
 * Environment: production
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Ahora, abre tu navegador web y accede a tu aplicación Flask utilizando la URL http://your-server-ip:5000. Deberías ver la siguiente pantalla:

Aplicación Flask

Ahora, pulsa CTRL + C en tu terminal para detener la aplicación Flask.

Configurar uWSGI

En primer lugar, crea un punto de entrada WSGI para indicar a tu servidor uWSGI cómo interactuar con él.

nano /var/www/html/myapp/wsgi.py

Añade las siguientes líneas para importar tu instancia Flask desde tu aplicación:

from myapp import app

if __name__ == "__main__":
    app.run()

Guarda y cierra el archivo cuando hayas terminado y luego prueba si uWSGI puede servir la aplicación utilizando el siguiente comando:

uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

Ahora, accede de nuevo a tu aplicación utilizando la URL http://your-server-ip:5000. Deberías ver la siguiente pantalla:

Acceder a la aplicación Flask en Ubuntu

Ahora, pulsa CTRL + C para detener la aplicación.

A continuación, ejecuta el siguiente comando para salir de tu entorno virtual:

deactivate

Configurar uWSGI

En este punto, uWSGI es capaz de servir a tu aplicación. Ahora, crea un archivo de configuración uWSGI con el siguiente comando:

nano /var/www/html/myapp/myapp.ini

Añade las siguientes líneas:

[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myapp.sock
chmod-socket = 660
vacuum = true

die-on-term = true

Guarda y cierra el archivo cuando hayas terminado.

Crear un archivo de servicio Systemd

A continuación, tendrás que crear un archivo de servicio systemd para gestionar el servicio uWSGI. Puedes crearlo con el siguiente comando:

nano /etc/systemd/system/myapp.service

Añade las siguientes líneas:

[Unit]
Description=uWSGI instance to serve myapp
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/html/myapp
Environment="PATH=/var/www/html/myapp/myappenv/bin"
ExecStart=/var/www/html/myapp/myappenv/bin/uwsgi --ini myapp.ini

[Install]
WantedBy=multi-user.target

Guarda y cierra el archivo cuando hayas terminado y luego vuelve a cargar el demonio systemd con el siguiente comando:

systemctl daemon-reload

A continuación, cambia la propiedad de tu aplicación a www-data y establece el permiso adecuado con el siguiente comando:

chown -R www-data:www-data /var/www/html/myapp
chmod -R 775 /var/www/html/myapp

A continuación, inicia tu aplicación y habilítala para que se inicie al reiniciar el sistema con el siguiente comando:

systemctl start myapp
systemctl enable myapp

También puedes comprobar el estado de tu aplicación con el siguiente comando:

systemctl status myapp

Deberías obtener la siguiente salida:

? myapp.service - uWSGI instance to serve myapp
     Loaded: loaded (/etc/systemd/system/myapp.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-09-13 08:38:08 UTC; 1min 53s ago
   Main PID: 662796 (uwsgi)
      Tasks: 6 (limit: 4691)
     Memory: 21.8M
     CGroup: /system.slice/myapp.service
             ??662796 /var/www/html/myapp/myappenv/bin/uwsgi --ini myapp.ini
             ??662808 /var/www/html/myapp/myappenv/bin/uwsgi --ini myapp.ini
             ??662809 /var/www/html/myapp/myappenv/bin/uwsgi --ini myapp.ini
             ??662810 /var/www/html/myapp/myappenv/bin/uwsgi --ini myapp.ini
             ??662811 /var/www/html/myapp/myappenv/bin/uwsgi --ini myapp.ini
             ??662812 /var/www/html/myapp/myappenv/bin/uwsgi --ini myapp.ini


Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x55e207e7a510 pid: 662796 (default app)
Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: *** uWSGI is running in multiple interpreter mode ***
Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: spawned uWSGI master process (pid: 662796)
Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: spawned uWSGI worker 1 (pid: 662808, cores: 1)
Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: spawned uWSGI worker 2 (pid: 662809, cores: 1)
Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: spawned uWSGI worker 3 (pid: 662810, cores: 1)
Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: spawned uWSGI worker 4 (pid: 662811, cores: 1)
Sep 13 08:38:08 ubuntu2004 uwsgi[662796]: spawned uWSGI worker 5 (pid: 662812, cores: 1)

Configurar Nginx como Proxy Inverso

A continuación, tendrás que configurar Nginx como proxy inverso para servir la aplicación Flask. Puedes hacerlo con el siguiente comando

nano /etc/nginx/sites-available/flask.conf

Añade las siguientes líneas:

server {
    listen 80;
    server_name flask.example.com;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/var/www/html/myapp/myapp.sock;
    }
}

Guarda y cierra el archivo cuando hayas terminado. A continuación, comprueba si Nginx tiene algún error de sintaxis con el siguiente comando:

nginx -t

Deberías ver la siguiente salida:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

A continuación, activa el host virtual Nginx con el siguiente comando:

ln -s /etc/nginx/sites-available/flask.conf /etc/nginx/sites-enabled/

Por último, reinicia el servicio Nginx para aplicar los cambios:

systemctl restart nginx

En este punto, Nginx está configurado para servir tu aplicación Flask.

Proteger la aplicación Flask con Let’s Encrypt SSL

A continuación, también se recomienda asegurar tu aplicación con el SSL gratuito Let’s Encrypt. En primer lugar, necesitarás instalar el cliente Certbot para instalar y gestionar el certificado SSL. Puedes instalarlo con el siguiente comando:

apt-get install python3-certbot-nginx -y

Una vez instalado, asegura tu sitio web con Let’s Encrypt SSL ejecutando el siguiente comando:

certbot --nginx -d flask.example.com

Se te pedirá que proporciones una dirección de correo electrónico válida y que aceptes las condiciones del servicio, como se muestra a continuación:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): [email protected]

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for flask.example.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/flask.conf

A continuación, elige si deseas o no redirigir el tráfico HTTP a HTTPS, como se muestra a continuación:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Escribe 2 y pulsa Intro para finalizar la instalación. Deberías ver el siguiente resultado:

Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/flask.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://flask.example.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=flask.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/flask.example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/flask.example.com/privkey.pem
   Your cert will expire on 2020-10-30. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

 - We were unable to subscribe you the EFF mailing list because your
   e-mail address appears to be invalid. You can try again later by
   visiting https://act.eff.org.

Ahora, tu sitio web Flask está protegido con Let’s Encrypt SSL. Puedes acceder a tu aplicación Flask utilizando la URL https://flask.example.com.

Conclusión

Enhorabuena! has desplegado con éxito la aplicación Flask con uWSGI y Nginx y la has asegurado con Let’s Encrypt SSL. Ahora puedes desarrollar y desplegar fácilmente tu aplicación Python con Flask. No dudes en preguntarme si tienes alguna duda.

También te podría gustar...