NGINX Conf 2018: Configuración de NGINX Unit para aplicaciones en producción: cómo servir un proyecto de Django

NGINX | 28 de noviembre de 2018

NGINX Unit es un servidor de aplicaciones totalmente dinámico que admite varios lenguajes, así como múltiples versiones de cada uno de ellos. Es dinámico porque permite utilizar la API JSON RESTful para modificar su configuración en memoria, sin interrumpir el servicio ni tener que volver a cargar la configuración.

En mi presentación de octubre en la NGINX Conf 2018, mostré cómo configurar una nueva aplicación en un entorno de producción existente. En concreto, con WordPress ejecutándose sobre PHP, implementé una aplicación de Python que utiliza el framework Django. También mostré cómo se puede cargar la configuración tanto desde un archivo como mediante un argumento especificado en una llamada a la API.

Este blog incluye todos los comandos y el código de configuración que utilicé en la demostración, para que le resulte más fácil adaptarlos a su propia implementación.

Requisitos previos

Para la demostración en NGINX Conf, tenía instalado el siguiente software:

  • Ubuntu 16.04
  • NGINX Plus, pero puede usar NGINX Open Source salvo que se indique lo contrario
  • NGINX Unit con todos los módulos de lenguaje instalados
  • Python 3
  • Django (sin configurar; de eso tratan la demostración y este blog)
  • root privilegios, o acceso equivalente mediante sudo (que utilizamos cuando es necesario)

También tenía instalados PHP y WordPress como aplicación existente.

Creación del proyecto de Django

  1. Cambia al directorio en el que vamos a crear nuestro proyecto de Django:
$ cd /var/www/
  1. Usa el comando django-admin startproject para inicializar el nuevo proyecto. Lo llamaremos djapp.
$ sudo django-admin startproject djapp
  1. Cambia al directorio del proyecto:
$ cd djapp
  1. Utilice el script manage.py para migrar la base de datos del proyecto, algo necesario en un proyecto recién creado. Django utiliza SQLite de forma predeterminada y, en la demostración, se mantiene esta opción, aunque puede utilizar cualquier base de datos que satisfaga las necesidades de su proyecto. El script manage.py se instala mediante el comando django-admin que ejecutamos en el paso 2; ejecuta los mismos comandos y acepta los mismos argumentos que django-admin, pero obtiene y utiliza automáticamente algunos ajustes específicos del proyecto, lo cual resulta útil. Para obtener más información, consulte la documentación de Django.
$ sudo python3 manage.py migrate
  1. Aunque no es estrictamente necesario para un proyecto de ejemplo como este, le recomendamos que cree una identidad de superusuario de Django:
$ sudo python3 manage.py createsuperuser
  1. Accede al subdirectorio que contiene el archivo settings.py, que se creó mediante el comando django-admin startproject en el paso 2.
$ cd /var/www/djapp/djapp
  1. Con tu editor de texto preferido, abre settings.py. En este caso, usamos nano:
$ sudo nano settings.py
  1. Busca la línea ALLOWED_HOSTS y añade el nombre de dominio, nombre de host o dirección IP de la aplicación:
ALLOWED_HOSTS = ['domain-name']
  1. Añade también la siguiente línea al final del archivo para indicar el directorio en el que se almacena todo el contenido estático que sirve la aplicación (consulta el paso 9).
STATIC_ROOT = '/var/www/djapp/djapp/static'
  1. Vuelve al directorio principal del proyecto (donde se encuentra manage.py).
$ cd ..
  1. Ejecuta el comando manage.py collectstatic para recopilar todos los archivos estáticos del proyecto de Django y guardarlos en la ubicación STATIC_ROOT definida en el paso 7.
$ sudo python3 manage.py collectstatic

Configuración de NGINX

De forma predeterminada, el propio Django sirve el contenido estático de un proyecto, pero NGINX Open Source y NGINX Plus ofrecen un rendimiento superior. Aquí configuramos NGINX Plus, aunque puede utilizar NGINX Open Source salvo por una función que se indica más adelante.

  1. Cambie al directorio /etc/nginx/conf.d, la ubicación convencional de los archivos de configuración HTTP específicos de una función (o, en nuestro caso, de una aplicación):
$ cd /etc/nginx/conf.d
  1. Crea un archivo llamado django.conf (de nuevo, usaremos nano):
$ sudo nano django.conf
  1. Inserte la siguiente configuración, que habilita el almacenamiento en caché. La configuración también incluye dos funciones exclusivas de NGINX Plus. Quite los comentarios de las directivas correspondientes si utiliza NGINX Plus y desea aprovechar estas funciones. Cabe señalar que, en la demostración de NGINX Conf, especifiqué la dirección IP de mi equipo local como segundo argumento de la directiva proxy_set_header. En un entorno de producción, resulta más adecuado utilizar la variable $host como se muestra a continuación.
# Upstream group for the backend (NGINX Unit running the Python application)
upstream django_unit {
    zone django_unit 64k;
    server 127.0.0.1:8000;
}
 
server {
    listen 8080;
    # Uncomment to collect metrics if using NGINX Plus and the NGINX Plus API
    #status_zone django;
      	
    # enable caching
    proxy_cache django_cache;
    proxy_cache_valid 200 60m;
 
    # root directory for static files
    root /var/www/djapp/djapp;
 
    # proxy to the NGINX Unit backend
    location / {
        proxy_pass http://django_unit;

        # Second argument must match your production hostname and the value of 
        # ALLOWED_HOSTS in settings.py
        proxy_set_header Host $host; 
 
        # Uncomment to enable active health checks if using NGINX Plus
        #health_check;
    }

    # Location for the static files collected from Django and served by 
    # NGINX Plus; can be empty (as here), because it inherits the value of the 
    # 'root' directive from its parent block
    location /static {
    }
}
  1. Compruebe que la sintaxis de la configuración sea válida:
$ sudo nginx –t
  1. Después de corregir los errores, vuelva a cargar la configuración:
$ sudo nginx -s reload

Configuración de NGINX Unit

Para terminar, debemos configurar NGINX Unit para que atienda las solicitudes dirigidas a la aplicación.

  1. Ejecute este comando curl para mostrar la configuración actual de NGINX Unit, que corresponde a WordPress ejecutándose en PHP. No muestro aquí la salida, pero la configuración de WordPress aparece en el paso 6 más adelante, junto con la configuración de la aplicación Python que vamos a añadir. Tenga en cuenta que utilizo sudo para el comando curl, aunque puede que no sea necesario para la mayoría de los comandos curl. En este caso es necesario porque, para acceder al socket UNIX, necesitamos los permisos de lectura y escritura que root tiene sobre él.
$ sudo curl --unix-socket /run/control.unit.sock http://localhost/config/
  1. Cambie al directorio de los archivos de configuración de NGINX Unit. Tenga en cuenta que estos archivos son opcionales y simplemente ofrecen una forma práctica de cargar conjuntos de configuraciones sin tener que introducir todos los datos como argumento en una llamada a la API de NGINX Unit. Dado que el contenido de los archivos se carga a través de la API (al igual que todos los datos de configuración), NGINX Unit desconoce la ubicación de los archivos y no puede leerlos automáticamente al iniciarse (a diferencia de NGINX Open Source y NGINX Plus). En su lugar, NGINX Unit guarda su estado de ejecución en un directorio independiente.
$ cd /etc/unit
  1. Crea un archivo llamado django.config (de nuevo, usaremos nano):
$ sudo nano django.config
  1. Añade el siguiente JSON, que representa nuestra aplicación de Python.
{
      "type": "python",
      "processes": 5,
      "module": "djapp.wsgi",
      "path": "/var/www/djapp"
}
  1. Ejecute este comando curl para cargar el JSON contenido en django.config como un nuevo objeto de aplicación gestionado por NGINX Unit, denominado djapp:
$ sudo curl -X PUT --data-binary @/etc/unit/django.config --unix-socket /run/control.unit.sock http://localhost/config/applications/djapp
  1. En este comando:
    • El método HTTP «PUT» crea un nuevo objeto de configuración de NGINX Unit en la ubicación indicada por el último argumento (la URL). Consulte el último punto a continuación.
    • El argumento --data-binary indica a curl que cargue el contenido de django.config exactamente como se ha proporcionado, conservando los saltos de línea y los retornos de carro, sin realizar ningún tipo de procesamiento.
    • El argumento --unix-socket define dónde escucha la API de NGINX Unit. (Utilizamos el comando sudo porque usamos el propietario predeterminado del socket, root.)
    • El último argumento localiza y asigna un nombre al nuevo objeto de aplicación que se rellenará con los datos de configuración en formato JSON de django.config: config es el objeto de configuración de nivel superior de NGINX Unit, applications es el objeto principal de los objetos de aplicación y djapp es el nombre del nuevo objeto de aplicación.
  2. Defina el objeto de escucha de la aplicación. En lugar de cargar un archivo de datos de configuración como en el paso 4, definimos los datos directamente en la línea de comandos de curl, especificando que la aplicación djapp escucha en el puerto 8000.
$ sudo curl -X PUT --data-binary '{"application":"djapp"}' --unix-socket /run/control.unit.sock 'http://localhost/config/listeners/*:8000'
  1. Repita el comando curl del paso 1 para mostrar la configuración de NGINX Unit, que ahora incluye nuestra aplicación de Python, djapp, resaltada en naranja:
$ sudo curl --unix-socket /run/control.unit.sock http://localhost/config/{
      "listeners": {
            "127.0.0.1:8090": {
                  "application": "script_index_php"
            },
 
            "127.0.0.1:8091": {
                  "application": "direct_php"
            },
 
            "*:8000": { "application": "djapp" }
      },
 
      "applications": {
            "script_index_php": {
                  "type": "php",
                  "processes": {
                        "max": 20,
                        "spare": 5
                   },
 
                  "user": "www-data",
                  "group": "www-data",
                  "root": "/var/www/wordpress",
                  "script": "index.php"
            },
 
            "direct_php": {
                  "type": "php",
                  "processes": {
                        "max": 5,
                        "spare": 0
                  },
 
                  "user": "www-data",
                  "group": "www-data",
                  "root": "/var/www/wordpress",
                  "index": "index.php"
                  },
 
            "djapp": { "type": "python", "processes": 5, "module": "djapp.wsgi", "path": "/var/www/djapp" }
      }
}

Resumen

En este artículo partimos de NGINX Unit ejecutando aplicaciones PHP para WordPress en producción y añadimos una aplicación Python. En la demostración, utilizo el panel de control de NGINX Plus para mostrar que las aplicaciones existentes no sufren ninguna interrupción al añadir una nueva aplicación, pero puede utilizar cualquier herramienta de supervisión del sistema, como el comando ps, para ese fin. La naturaleza dinámica de la configuración de NGINX Unit ahorra recursos a las aplicaciones en ejecución y garantiza que no haya tiempo de inactividad en las nuevas implementaciones, así como una transición fluida entre las versiones de las aplicaciones.

Para obtener más información, visita unit.nginx.org.


Compartir
Etiquetas: Python, F5 NGINX, Tech

Artículos relacionados del blog

Únete a F5 NGINX en AppWorld 2024
NGINX | 04/01/2024

Únete a F5 NGINX en AppWorld 2024

Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
NGINX | 26/09/2023

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source

La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.

Exposición de APIs en Kubernetes
NGINX | 10/03/2022

Exposición de APIs en Kubernetes

La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
NGINX | 23/08/2021

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto

Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.

Presentamos NGINX Plus R22
NGINX | 09/06/2020

Presentamos NGINX Plus R22

NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.

Presentamos NGINX Plus R17
NGINX | 11/12/2018

Presentamos NGINX Plus R17

NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.