Tabla de Contenidos
Flask - 2 - Producción
Introduction
Tutorial de Desarrollo de una Aplicación con Flask y Gestión con systemd
Referencias: Flask mega tutorial
Preparación del Entorno de Producción en Linux Ubuntu
Instalación de Dependencias
En tu máquina de producción con Linux Ubuntu, instala las dependencias necesarias:
sudo apt update sudo apt install python3-pip nginx pipenv sudo systemctl enable nginx
Una alternativa para usar un pipenv más actualizado es instalarlo con pip:
sudo apt install python3-pip nginx pip install --user pipenv
Directorio de producción.
En lugar de ceder toda la propiedad a www-data, utilizaremos un esquema de
permisos compartidos. Esto permite que tu usuario edite archivos y ejecute
pipenv sin usar sudo, mientras que www-data mantiene el acceso
necesario para servir la aplicación.
sudo mkdir /var/www/my_flask_app
Debemos copiar todos los ficheros que hemos preparado en el entorno de
desarrollo al nuevo entorno de producción, para ello podemos usar scp,
rsync o unison.
Fichero wsgi.py
En entornos de producción, Flask no se ejecuta mediante app.run(), ya que este método lanza un servidor de desarrollo que no está diseñado para ser seguro, eficiente ni persistente. En su lugar, se utiliza un servidor WSGI (Web Server Gateway Interface), como Gunicorn o uWSGI, que actúa como intermediario entre el servidor web (por ejemplo, Nginx) y la aplicación Python.
El fichero wsgi.py define el punto de entrada estándar de la aplicación,
exponiendo el objeto app para que el servidor WSGI pueda importarlo y
gestionarlo. De este modo, wsgi.py desacopla el código de la aplicación del
mecanismo de ejecución, permitiendo una ejecución robusta, escalable y adecuada
para producción.
Crea el fichero wsgi.py con el siguiente contenido:
====== wsgi.py ====== from app import app
Configuración de Grupos
Añade tu usuario personal al grupo de Nginx para que ambos compartan privilegios:
====== Añadir el usuario actual al grupo www-data ====== sudo usermod -aG www-data $USER
Nota: Se debe cerrar sesión y volver a entrar (o reiniciar el servidor) para que este cambio se aplique.
Asignación de Propiedad y Bit de Grupo
Configuramos tu usuario como propietario y www-data como grupo responsable.
Aplicaremos el setgid bit, que garantiza que cualquier archivo nuevo creado
herede automáticamente el grupo www-data.
====== Cambiar propietario al usuario actual y grupo a www-data ====== sudo chown -R $USER:www-data /var/www/my_flask_app ====== Dar permisos de lectura/escritura/ejecución a dueño y grupo (775) ====== sudo find /var/www/my_flask_app -type d -exec chmod 775 {} + sudo find /var/www/my_flask_app -type f -exec chmod g+rw {} + ====== Aplicar el bit de grupo persistente (setgid) a todos los directorios ====== sudo find /var/www/my_flask_app -type d -exec chmod g+s {} +
Ventajas de este método
- Tu Usuario: Puedes usar
git pull,pipenv instally editar código sinsudo. - Nginx / www-data: Grupo (rwx) Puede leer archivos estáticos y escribir en el socket o logs.
- Seguridad: Los usuarios que no pertenecen al grupo
www-datano tienen acceso.
Verificación de permisos
Para confirmar que la configuración es correcta, ejecuta:
ls -la /var/www/my_flask_app
La salida debería mostrar los permisos como drwxrwxr-x y los dueños como
tu_usuario www-data.
Configuración de Nginx
Configura Nginx para servir la aplicación Flask. Crea un nuevo archivo de
configuración en /etc/nginx/sites-available/my\_flask\_app:
server { listen 80; server_name your_domain; access_log /var/log/nginx/my_flask_app.access.log; error_log /var/log/nginx/my_flask_app.error.log; location / { proxy_pass http://unix:/var/www/my_flask_app/my_flask_app.sock; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect off; proxy_buffering off; } }
- server\_name es donde va el dominio. Es el que usarás para acceder a la aplicación desde internet.
- access\_log y error\_logs especifican la ruta de los archivos de log.
- location es donde el
reverse proxyde nginx accede a la aplicación Flask. - proxy\_redirect off: Evita que Nginx reescriba automáticamente cabeceras Location y Refresh que devuelve la aplicación backend (Gunicorn/Flask). Evitamos problemas de redirección difíciles de depurar.
- proxy\_buffering off: Desactivamos el buffering de respuestas, que es lo más conveniente para webs dinámicas.
Habilitamos el sitio creando un enlace al fichero correspondiente de
sites-enabled y reiniciando nginx.
sudo ln -s /etc/nginx/sites-available/my_flask_app /etc/nginx/sites-enabled sudo nginx -t sudo systemctl restart nginx sudo systemctl status nginx
Instalación de Gunicorn
Instala Gunicorn en el entorno virtual de producción. Se debe ejecutar export
PIPENV_VENV_IN_PROJECT=1 antes de hacer el pipenv install en el servidor,
o el servicio de systemd fallará al no encontrar la ruta de Gunicorn.
pipenv install gunicorn
Mientras estas en el entorno virtual comprueba la ruta de gunicorn. Toma
nota de esta ruta. Se necesitará para configurar el servicio systemd.
$ which gunicorn
/var/www/my_flask_app/.venv/bin/gunicorn
Testing with gunicorn
Ahora comprobaremos el funcionamiento con gunicorn. Para la prueba ejecutamos
gunicorn directamente. Después lo configuraremos en el servicio systemd.
gunicorn --workers 4 --bind 0.0.0.0:5000 wsgi:app
[2024-02-20 20:57:21 -0500] [4936] [INFO] Starting gunicorn 21.2.0 [2024-02-20 20:57:21 -0500] [4936] [INFO] Listening at: http://0.0.0.0:5000 (4936) [2024-02-20 20:57:21 -0500] [4936] [INFO] Using worker: sync [2024-02-20 20:57:21 -0500] [4937] [INFO] Booting worker with pid: 4937 [...]
Hacemos la comprobación:
curl -O - localhost:5000
Deberíamos obtener la salida de la página inicial de la aplicación.
Press CTRL+C to stop the Gunicorn server.
Esta prueba NO usa nginx, NO usa systemd y NO representa el entorno
final, sólo comprueba el funcionamiento de gunicorn.
Creación del Servicio systemd
Crea un archivo de servicio systemd para gestionar la aplicación. Crea un
archivo /etc/systemd/system/my_flask_app.service con el siguiente
contenido:
[Unit] Description=Gunicorn instance to serve my_flask_app After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/var/www/my_flask_app Environment="PATH=/var/www/my_flask_app/.venv/bin" ExecStart=/var/www/my_flask_app/.venv/bin/gunicorn --workers 3 --bind unix:/var/www/my_flask_app/my_flask_app.sock -m 007 wsgi:app [Install] WantedBy=multi-user.target
- User: Establece el usuario con permisos para el directorio del proyecto.
- Group: Establece el grupo con permisos para el directorio del proyecto.
- Environment: Establece la ruta al directorio de ejecutables dentro del entorno virtual.
- WorkingDirectory: Establece el directorio base donde están los ficheos del proyecto.
- ExecStart: Establece la ruta al ejecutable de
gunicorndentro del entorno virtual, así como opciones de ejecución. - –workers N: Establece el número de workers. Ajustar el número posteriormente si hay algún problema. No más de 12.
- –bind unix:: Asociamos la ejecución de
gunicorna un socket Unix. - wsgi:app: wsgi es el nombre del fichero sin la extensión
.py.appes la instancia de la aplicación Flask dentro del fichero. - -m 007: Para que Nginx pueda comunicarse con el socket creado por Gunicorn sin errores de “Permission Denied”, es fundamental añadir la máscara de permisos
-m 007en la configuración del servicio.
Habilitar y Iniciar el Servicio
Habilita y inicia el servicio con los siguientes comandos:
sudo systemctl enable my_flask_app sudo systemctl start my_flask_app
/etc/hosts provisional para pruebas en local
La aplicación Flask ya no es accesible a través del puerto 5000 que usábamos
antes, sino a través de systemd, gunicorn y nginx. Para acceder a la
aplicación hay que usar el nombre de dominio que hemos puesto en la
configuración. Pero es conveniente probar en local antes de intentar un acceso
desde internet. Para ello vamos a editar el fichero /etc/hosts del cliente e
incluiremos una sentencia similar a esta, con la IP de la red local del
servidor.
192.168.12.34 my_flask_app
Ahora podemos acceder a la aplicación con un browser a través del nombre de
dominio: http://my_flask_app.
Deberíamos obtener la primera página de nuestra aplicación nuevamente.
Ahora la aplicación está probada y es posible modificar el DNS para que apunte a
la dirección pública del servidor, volviendo a dejar el fichero /etc/hosts
del cliente como estaba.
En caso de que no funcione desde internet habrá que comprobar direcciones IP externas y firewalls tanto en el servidor cómo en el router.