Recientemente he estado trabajando en cómo integrar el Framework de Python Flask con un servidor web corriendo bajo Centos7 y así poder tenerlo siempre disponible con las ventajas que ofrecen este tipo de soluciones. Para esta ocasión el servidor web escogido fue Apache.
No fue una tarea fácil, pero finalmente conseguí hacerlo funcionar, y el resultado quería compartirlo con la comunidad por si le pudiera servir de ayuda a alguien.
Flask es un Framework minimalista de Python destinado a la creación de aplicaciones web y API Rest con muy pocas líneas de código. Al decir que es minimalista nos referimos a que en comparación a otros Frameworks, como Django, no dispone de todos los módulos aunque sí se podrá complementar con librerías de terceros que ofrezcan las funcionalidades de las que carece. Está basado en la especificación WSGI de Werkzeug y el motor de templates Jinja2 y tiene una licencia BSD. Sus ventajas son muchísimas, por lo que te animo a que investigues un poco más sobre este interesante Framework.
Los entornos virtuales de Python nos van a permitir crear estancias aisladas en donde podremos instalar y usar librerías sin que afecte a la instalación global o a otros entornos virtuales creados. Es una gran forma de probar librerías en diferentes desarrollos y evitar incompatibilidades entre estas o ante la necesidad de usar versiones distintas de una misma librería.
Esta entrada no se centrará en la instalación de versiones de Python. Recomendamos utilizar la versión 3, aunque serviría con la 2.7, por lo que os dejo un enlace en donde se explica en detalle como hacerlo de forma muy sencilla https://linuxize.com/post/how-to-install-python-3-on-centos-7/. Ignorad la parte en donde se explica la instalación de los entornos virtuales, ya que no es compatible con la integración del WSGI de Apache que vamos a utilizar en este tutorial.
Vamos al lío!!!!!
Tabla de contenidos
Requisitos
- Centos 7
- Python 3.6
- Pip
- Librería virtualenv de Python
- Librería Flask de Python
- Apache
- Apache Web Server Gateway Interface – WSGI
Apache WSGI
Instalamos el módulo WSGI para Apache:
sudo yum install mod_wsgi
Comprobamos que se ha instalado correctamente:
httpd -M | grep wsgi
De no estarlo tocará investigar un poco.
Pip y virtualenv
Ahora instalamos la versión de Pip compatible con nuestra versión de Python (2 o 3). No indico ninguna versión en el comando para que quede a elección del usuario:
sudo yum install python-pip
Ahora toca instalar los entornos virtuales de Python:
sudo pip install virtualenv
Por ejemplo, en mi caso sería pip3 install virtualenv.
Entorno virtual
Para crear un entorno virtual primero creamos el directorio en el que vamos a trabajar y nos ubicamos en el:
mkdir /path/to/your/app cd /path/to/your/app
Ahora ejecutamos el comando para crear el entorno virtual. Le tenemos que indicar un nombre al entorno virtual, lo que creará un nuevo directorio en donde se ubicarán las librerías que utilizaremos únicamente en este entorno aislado y los comandos para activar/desactivar el entorno virtual. Indicar la versión de Python que se va a utilizar sustituyéndolo en donde aparece pythonX:
virtualenv env_name -p pythonX
Por ejemplo, en mi caso uso Python en su versión 3, por lo que indico -p python3 en el comando.
Activamos el entorno virtual:
source env_name/bin/activate
Ahora en el promp aparece el nombre que le dimos al entorno virtual al comienzo de la línea de comandos:
(env_name)user@host:~/app$
Flask
Instalamos la librería Flask con el comando pip:
pip install flask
Ahora tendremos una instalación de Flask únicamente para el entorno virtual en el que nos encontramos.
Creamos en el mismo directorio del entorno virtual una aplicación sencilla de Flask:
nano /path/to/your/app/my_app.py
Esta aplicación devolverá un sencillo «Hola mundo!» por pantalla. Recordar cambiar el host en donde escuchará la aplicación, al final del documento (X.X.X.X). Se puede indicar una IP del servidor o un nombre de host que resuelva a dicha IP:
#!/usr/bin/python3 from flask import Flask, request app = Flask(__name__) @app.route('/') def index(): return 'Hola mundo!' if __name__ == '__main__': app.run(debug=True, host=X.X.X.X)
Con el flag debug=True podemos hacer cambios en caliente sobre el documento sin tener que reiniciar el servidor web.
WSGI config
Creamos un archivo en donde indicamos al servidor WSGI cómo activar el entorno virtual y ejecutar la aplicación de Flask recién creada. Tendrá una extensión .wsgi y se encontrará en el mismo path que el entornor virtual y la aplicación de Flask creada:
nano /path/to/your/app/app.wsgi
En este archivo importaremos la aplicación creada y la renombraremos, además de indicar el comando para activar el entorno virtual del que hará uso el servidor web, como veremos más adelante:
from my_app import app as application activate_this = '/path/to/my/app/nom_entorno_virt/bin/activate_this.py' execfile(activate_this, dict(__file__=activate_this))
Apache y VirtualHost
Primero configuramos Apache para habilitar el directorio en donde se ubicarán los archivos de configuración de los VirtualHost que tendremos en el servidor web:
nano /etc/httpd/conf/httpd.conf
Tendremos que asegurarnos de disponer de la siguiente línea:
IncludeOptional sites-enabled/*.conf
Y si usamos el flag de Flask debug=True debemos de agregar también esta:
WSGIRestrictStdout Off
Ahora creamos el contenido del VirtualHost imaginando que nuestra aplicación escuchará hará uso del dominio example.com:
sudo nano /etc/httpd/sites-available/example.conf
<VirtualHost *:80> WSGIDaemonProcess my_app user=apache group=apache threads=5 python-path=/path/to/my/app:/path/to/my/app/lib/python3.6/site-packages WSGIScriptAlias / /path/to/my/app/my_app.wsgi # You have to add every Flask route as WSGI alias: WSGIScriptAlias /(.*) /path/to/my/app/my_app.wsgi/(.*) <Directory /var/www/html/flask> WSGIProcessGroup my_app WSGIApplicationGroup %{GLOBAL} Order deny,allow Allow from all </Directory> ServerName example.com ServerAdmin example@example.com DocumentRoot /path/to/your/app # DocumentRoot /home/ubuntu/test # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, # error, crit, alert, emerg. # It is also possible to configure the loglevel for particular # modules, e.g. #LogLevel info ssl:warn LogLevel warn ErrorLog /var/log/httpd/my_app-error.log CustomLog /var/log/httpd/my_app-access.log combined </VirtualHost>
Ahora creamos el enlace simbólico desde el directorio sites-available al de sites-enabled, configurado previamente en el archivo de configuración de Apache:
ln -s /etc/httpd/sites-available/example.conf /etc/httpd/sites-enabled/example.conf
Cambiamos los permisos del directorio en donde tenemos la aplicación ubicada:
sudo chown -vR apache: /path/to/your/app sudo chmod -vR g+w /path/to/your/app
Y para finalizar reiniciamos el servidor web:
sudo service httpd restart
Acceso
Ahora si accedemos a la URL que hemos configurado en el servidor web, en nuestro caso http://example.com, veremos la aplicación creada en un entorno virutal de Python con Flask y administrada por el servidor web Apache:
Enlaces de interés
Flask pincha aquí.
WSGI pincha aquí.
Python 3 instalación en Centos 7 – https://linuxize.com/post/how-to-install-python-3-on-centos-7/
Apache wsgi pincha aquí.