En la entrada anterior aprendimos cómo configurar una máquina huésped LEMP con Vagrant y Ansible para probar aplicaciones PHP. Sin embargo, en la actualidad, se pueden usar otros lenguajes de programación para el desarrollo web aparte de PHP.

Python es un popular lenguaje de programación, de fácil aprendizaje, que nos permitirá crear con facilidad aplicaciones web gracias a sus múltiples módulos y paquetes de terceros.

A diferencia de PHP, Python no nació con el objetivo de ser un lenguaje de servidor diseñado para el desarrollo web y no está tan integrado con servidores web (tales como Apache). Es por esto que deberemos usar algún tipo de módulo o pasarela para que funcione.

Para esta entrada, instalaremos uWSGI, una interfaz de pasarela de servidor web (WSGI), dentro de la máquina huésped de Vagrant y conectaremos Nginx a ésta.

Creando una aplicación de prueba

Vamos a crear una simple aplicación de prueba usando Flask.

Flask es un framework minimalista escrito en Python que te permite crear aplicaciones web rápidamente y con un mínimo número de líneas de código.

Wikipedia

Un framework para aplicaciones web es una gran herramienta que facilita mucho el desarrollo de aplicaciones web en Python.

Vamos a guardar los archivos de configuración de nuestra aplicación en el subdirectorio vagrant/www/test:

vagrant/www/test
├── requirements.txt
├── test.ini
└── test.py

Archivo requirements

Un entorno virtual es un árbol de directorios independiente que contiene una instalación de Python para una versión específica de Python, además de un número adicional de paquetes

Documentación de Python

Los entornos virtuales nos dan la posibilidad de aislar cada una de nuestras aplicaciones Python. De esta forma, podemos usar PIP para instalar distintas versiones de paquetes sin que haya conflictos con las versiones del mismo paquete para otra aplicación.

¿Y cómo le decimos a PIP qué paquetes y qué versiones debe instalar? Pues usando un archivo requirements para cada aplicación.

Puesto que nuestra aplicación de prueba sólo necesita Flask, lo añadiremos al archivo requirements.txt:

Flask>=0.12

Archivo de configuración de uWSGI

Para indicar a uWSGI cómo lanzar nuestra aplicación, configuraremos algunos parámetros en el archivo test.ini que será cargado por uWSGI durante el arranque:

[uwsgi]
plugins = python3
socket = /tmp/test.sock
venv = /opt/virtualenvs/test
chdir = /vagrant/www/test
wsgi-file = test.py
callable = app

Aquí especificamos la versión de Python a usar, el archivo socket, la ruta del entorno virtual, el directorio de los archivos de nuestra aplicación, el archivo que contiene la aplicación y qué objeto se debe llamar.

Aplicación Python

La aplicación web per se estará en test.py:

#!/usr/bin/env python3

from flask import Flask

app = Flask(__name__)


@app.route('/test')
def test():
    return '<p style="background: aliceblue;">Hello Wold</p>\n'


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

Esto simplemente manda el texto Hello World (sobre un fondo azul) al navegador web cuando nos conectamos al servidor.

Configuración de Ansible

Ahora deberemos modificar nuestra configuración de Ansible de forma que instale todos los paquetes necesarios y cargue los archivos de configuración apropiados.

Variables globales

Antes de nada, puesto que usaremos algunas variables que son comunes a más de un rol, vamos a crear un archivo para almacenar estas variables globales. En el subdirectorio vagrant/cfg/group_vars creamos un archivo llamado all.yml para todos los roles:

---
base_dir:   '/vagrant/www'
venv_dir:   '/opt/virtualenvs'

Indicamos el directorio que Nginx usará como raíz y el directorio en el que se crearán los entornos virtuales de Python.

En este mismo archivo, incluiremos el nombre/directorio de nuestras aplicaciones:

apps:
  - name: test

Rol Python

Ahora vamos a añadir un nuevo rol a nuestra configuración de forma que se cumplan todas las dependencias de Python necesarias. Guardaremos los archivos en el subdirectorio vagrant/cfg/roles/python:

vagrant/cfg/roles/python
├── handlers
│   └── main.yml
└── tasks
    └── main.yml

Las tareas se guardan en tasks/main.yml:

---
- name: Instala Python
  package: name={{ item }} state=present
  with_items:
    - python3-pip
    - python3-venv
    - uwsgi
    - uwsgi-plugin-python3
  notify:
    - arranca uwsgi

- name: Instala paquetes PIP
  pip:
    requirements: '{{ base_dir }}/{{ item.name }}/requirements.txt'
    virtualenv: '{{ venv_dir }}/{{ item.name }}'
    virtualenv_command: pyvenv
  with_items:
    - '{{ apps }}'

- name: Enlace archivo uWSGI
  file:
    src: '{{ base_dir }}/{{ item.name }}/{{ item.name }}.ini'
    dest: '/etc/uwsgi/apps-enabled/{{ item.name }}.ini'
    force: yes
    state: link
  with_items:
    - '{{ apps }}'
  notify:
    - reinicia uwsgi

Los pasos son:

  1. Usando el módulo package, instalamos los paquetes PIP y venv de Python 3, así como uWSGI y su plugin de Python 3.
  2. Luego, usando el módulo pip, leemos el archivo requirements.txt para cada aplicación e instalamos sus paquetes en un entorno virtual.
  3. Activamos entonces la aplicación creando un enlace simbólico al archivo INI de la aplicación en el directorio /etc/uwsgi/apps-enabled usando el módulo file.

Y no nos olvidemos de los handlers para activar y reiniciar el servicio cuando sea necesario. Añadimos esto al archivo handlers/main.yml:

---
- name: arranca uwsgi
  service: name=uwsgi enabled=yes state=started

- name: reinicia uwsgi
  service: name=uwsgi state=restarted

Por último, modificamos vagrant/cfg/site.yml para añadir este nuevo rol:

---
- name: Configura servidor LEMP
  hosts: lemp
  roles:
    - mariadb
    - php
    - python
    - nginx

Rol Nginx

También tenemos que modificar la plantilla para nuestro rol Nginx en vagrant/cfg/roles/nginx de forma que cargue nuestras aplicaciones.

Para ello, editamos templates/default y añadimos lo siguiente dentro de la directiva server:

{% for item in apps %}
  location /{{ item.name }} {
    include uwsgi_params;
    uwsgi_pass unix:/tmp/{{ item.name }}.sock;
  }
{% endfor %}

Esto configurará Nginx para usar cada una de nuestras aplicaciones para su correspondiente subruta.

Ejecutando la aplicación de prueba

Podemos ahora iniciar nuestra máquina huésped con Vagrant usando el comando vagrant up. Tras el arranque, podremos abrir nuestra aplicación de prueba dirigiendo nuestro navegador web a http://172.28.128.10/test:

Aplicación de prueba

Conclusión

Usar Python como backend para nuestras aplicaciones web no es tan sencillo como poner unas cuantas líneas de código PHP en el archivo index.php pero, con unos pocos cambios, podemos crear una aplicación funcional y tener acceso al potencial de los paquetes de Python.

Leer más