Desplegando aplicaciones flask con apache2 + gunicorn
Vamos a explicar paso por paso como configurar apache y ngnix para que usen gunicorn para servir aplicaciones web python, en concreto, la aplicación guestbook.
En primer lugar tenemos que instalar los paquetes que usaremos para el ejercicio, incluyendo los paquetes necesarios para crear el entorno virtual y las dependencias de guesbook:
apt install python3-venv libapache2-mod-wsgi-py3 git redis
Ahora creamos el entorno virtual en el que instalaremos flask:
python3 -m venv flask
Activamos el entorno virtual e instalamos flask y gunicorn con pip:
source flask/bin/activate
pip install flask gunicorn
Ya podemos clonar el repositorio de github con la aplicación guestbook:
git clone https://github.com/josedom24/guestbook.git
No se nos puede olvidar crear el fichero wsgi.py en el mismo directorio donde se encuentra la aplicación app.py, añadiendo la siguiente línea al fichero wsgi.py:
nano wsgi.py
from app import prog as application
Con esto ya podríamos ejecutar la aplicación y acceder a ella si usamos el comando específico de gunicorn:
gunicorn -w 2 -b :8080 wsgi:application
Si accedemos al puerto 8080 de la máquina veremos la aplicación en funcionamiento:

Con la opción -w indico el número de procesos que van a servir las peticiones, y con la opción -b indico la dirección y el puerto de escucha.
Ahora procedamos a crear una unidad systemd para poder controlar el proceso de gunicorn de forma más sencilla. Para ello creamos el fichero gunicorn-guestbook.service en el directorio /etc/systemd/system/:
nano /etc/systemd/system/gunicorn-guestbook.service
[Unit]
Description=gunicorn-guestbook
After=network.target
[Install]
WantedBy=multi-user.target
[Service]
User=www-data
Group=www-data
Restart=always
ExecStart=/home/vagrant/flask/bin/gunicorn -w 2 -b :8080 wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
WorkingDirectory=/home/vagrant/guestbook/app
Environment=PYTHONPATH='/home/vagrant/guestbook/app:/home/vagrant/flask/lib/python3.9/site-packages'
PrivateTmp=true
Activamos la unidad de systemd, y la iniciamos:
systemctl enable gunicorn-guestbook.service
systemctl start gunicorn-guestbook.service
Si cambiamos el contenido de la unidad tendremos que recargar el demonio:
systemctl daemon-reload
Con esta configuración ya podemos controlar gunicorn con systemctl, como si fuera un servicio más. Ahora podemos configurar apache o nginx como un proxy inverso que haga uso del servicio que hemos creado para servir las aplicaciones python.
- En apache2:
Creamos un virtualhost con la siguiente configuración:
nano guestbook.conf
<VirtualHost *:80>
ServerName www.guestbook.com
ServerAdmin webmaster@localhost
DocumentRoot /home/vagrant/guesbook/app
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
<Directory /home/vagrant/guesbook/app>
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Una vez creado el virtualhost lo habilitamos:
a2ensite guestbook.conf
También debemos habilitar los módulos del proxy:
a2enmod proxy proxy_http
Reiniciamos el servicio y probamos la conexión (hay que recordar añadir la dirección estática al fichero /etc/hosts del anfitrión):
systemctl reload apache2

Podemos acceder a la página, por lo que podemos decir que funciona.
- En nginx:
Creamos un virtualhost con la siguiente configuración:
nano guestbook
server {
listen 80;
listen [::]:80;
root /home/vagrant/guestbook/app;
index index.html index.php index.htm index.nginx-debian.html;
server_name www.guestbook.com;
location / {
proxy_pass http://localhost:8080;
include proxy_params;
}
}
Creamos el enlace simbólico del virtualhost y reiniciamos el servicio:
ln -s /etc/nginx/sites-available/guestbook /etc/nginx/sites-enabled/
systemctl reload nginx
Ahora probamos a acceder a guestbook desde el navegador:

También funciona al acceder a www.guestbook.com cuando lo sirve nginx.