Volver al blog

Configuración de Django con PostgreSQL, Nginx y Gunicorn en Ubuntu 20.04

Configuración de Django con PostgreSQL, Nginx y Gunicorn en Ubuntu 20.04

Django es un framework de aplicaciones web gratuito y de código abierto que está construido en el Python lenguaje de programación. Django es superrápido, seguro y altamente escalable. En manos de un desarrollador experimentado, Django puede establecer rápidamente un sitio web potente. Puede integrarse perfectamente con servidores web populares (Apache, Nginx), y bases de datos (MySQL, MariaDB, PostgreSQL, Oracle, y SQLite), etc. Django impulsa algunos de los sitios web más grandes del mundo como Instagram, Mozilla y la NASA. Esta guía demuestra cómo configurar la base de una aplicación web con la ayuda de Django con PostgreSQL, Nginx y Gunicorn en Ubuntu 20.04.

Requisitos previos

Esta guía requiere que esté ejecutando un servidor Ubuntu 20.04 configurado con un cortafuegos básico y un usuario no raíz con privilegios sudo. Consulte esta guía detallada sobre cómo configurar un servidor Ubuntu. Siga este tutorial para configurar un usuario no raíz con privilegios sudo. También puede configurar un cortafuegos Iptables siguiendo los pasos de esta guía.

Instalaremos Django dentro de un entorno virtual. Tener un entorno específico para el proyecto permite una gestión más sencilla de múltiples proyectos desde el mismo servidor. Una vez que las bases de datos y las aplicaciones estén en su lugar, implementaremos el servidor de aplicaciones Gunicorn. Gunicorn será la interfaz de la aplicación que traduce las solicitudes de los clientes de HTTP a llamadas de Python que nuestra aplicación pueda utilizar. Luego, implementaremos Nginx frente a Gunicorn por su rápido rendimiento en el manejo de conexiones y sus características de seguridad fáciles de implementar.

Instalación de los paquetes necesarios

Primero, comience instalando todos los paquetes necesarios. Afortunadamente, todos estos paquetes están disponibles directamente en los repositorios oficiales de paquetes de Ubuntu. Abra la terminal y actualice la caché de paquetes de APT:

La lista de paquetes depende de si la aplicación web va a utilizar Python 2 o Python 3. Ejecute el siguiente comando para instalar Django con Python 3:

Django 1.11 LTS es la última versión de Django que admitirá Python 2. Si tiene la intención de utilizar Django con Python 2, instale los siguientes paquetes:

Base de datos y usuario de PostgreSQL

En cuanto a la solución de base de datos, utilizaremos PostgreSQL. Es un sistema de base de datos objeto-relacional potente y de código abierto. PostgreSQL ofrece confiabilidad, robustez y rendimiento. Para obtener pasos detallados sobre cómo configurar PostgreSQL, consulte esta guía sobre cómo configurar PostgreSQL en el servidor Ubuntu. Para la presente guía, configuraremos una base de datos y un usuario dedicados para nuestra aplicación Django.

Por defecto, PostgreSQL implementa la “autenticación de pares” como esquema de autenticación para conexiones locales. En resumen, la “autenticación de pares” autenticará el inicio de sesión si el nombre de usuario del sistema operativo coincide con un nombre de usuario de PostgreSQL válido. Durante la instalación, PostgreSQL configuró un usuario del sistema operativo postgres para corresponder al usuario administrador de PostgreSQL postgres. Inicie sesión en la sesión interactiva de la consola de PostgreSQL como postgres utilizando el siguiente comando:

Llegará a la consola de PostgreSQL. El primer paso es crear una base de datos dedicada para el proyecto. Para la demostración, la base de datos se llamará viktor_project:

El siguiente paso es crear un usuario dedicado para la base de datos del proyecto. El usuario debe tener un nombre de usuario seguro. Para la demostración, el nombre de usuario será viktor_project_user:

Ahora, modificaremos algunos parámetros:

  • Ciertos parámetros de conexión. En resumen, no será necesario consultar y establecer los valores correctos cada vez que se establezca una conexión. Mejora enormemente el rendimiento de la base de datos.
  • Codificación predeterminada a UTF-8. Es una codificación universal y Django la espera.
  • Esquema de aislamiento de transacciones predeterminado a “read committed”. Bloquea la lectura de transacciones no confirmadas.
  • Zona horaria a UTC.

Todos estos cambios de parámetros son recomendados por el propio proyecto Django. Para implementar estos cambios, ejecute los siguientes comandos. No olvide cambiar el nombre de usuario de la base de datos por el correcto:

Cambie el administrador de la base de datos al usuario de base de datos dedicado:

Nuestro trabajo con PostgreSQL ha terminado por ahora. Salga de la consola interactiva de PostgreSQL:

Exit the PostgreSQL interactive shell

Entorno virtual de Python

Con la base de datos preparada, ahora podemos enfocarnos en establecer el resto de los requisitos del proyecto. Para una gestión más sencilla, estableceremos un entorno virtual e instalaremos todos los requisitos de Python allí. Para generar un entorno virtual, necesitamos virtualenv. Se puede instalar fácilmente con pip.

Los siguientes comandos actualizarán pip e instalarán virtualenv. Para Python 3, ejecute los siguientes comandos:

Para Python 2, ejecute los siguientes comandos en su lugar:

Una vez que virtualenv esté instalado, es hora de crear un entorno virtual. A continuación, cree un directorio dedicado para el entorno virtual:

Después de eso, cambie el directorio activo actual al directorio dedicado para el entorno virtual:

Dentro del directorio, ejecute el siguiente comando. La herramienta virtualenv creará un entorno virtual con el nombre del proyecto:

Creará un subdirectorio con el nombre del proyecto. El subdirectorio contendrá una versión local de Python y pip. Ofrece flexibilidad para instalar y configurar un entorno de Python aislado para el proyecto.

El siguiente comando activará el entorno virtual:

activate the virtual environment

El indicador de la terminal cambiará indicando que está operando dentro de un entorno virtual de Python. Ahora que estamos dentro del entorno virtual, instalaremos los requisitos de Python necesarios. Necesitamos Django, Gunicorn y psycopg2 (adaptador de PostgreSQL). El siguiente comando le indicará al pip local que instale los componentes:

Incluso si está utilizando Python 3, pip es el comando correcto. Esto se debe a que dentro del entorno virtual, pip3 pasa a llamarse pip.

Nuevo proyecto Django

Con los componentes de Python listos, podemos comenzar a trabajar con los archivos reales del proyecto Django.

  • Creación de un proyecto Django

El directorio del proyecto ya está establecido. Le diremos a Django que instale sus archivos allí. Este procedimiento generará un directorio de segundo nivel que contendrá el código real. El directorio también contendrá un script de administración. La clave es que le estamos indicando a Django el directorio de destino de forma explícita en lugar de dejar que decida el directorio relativo al actual:

Django creará el proyecto en consecuencia. Aquí están algunos de los archivos y directorios importantes en los que nos enfocaremos. Los nombres de directorios y archivos se utilizan de acuerdo con la demostración.

  • ~/viktor_project/manage.py: El script de gestión de proyectos de Django.
  • ~/viktor_project/viktor_project/: Es el paquete que contiene el proyecto Django. Debe contener los archivos __init__.py, settings.py, urls.py, asgi.py y wsgi.py.
  • Ajustando la configuración del proyecto

Una vez creado el proyecto, lo primero que hay que hacer es ajustar su configuración. Abre settings.py en un editor de texto:

La primera directiva que buscamos es ALLOWED_HOSTS. Define los servidores o nombres de dominio que pueden conectarse a la instancia de Django. Si alguna solicitud entrante con una cabecera Host no coincide con la lista de ALLOWED_HOSTS, creará una excepción. Django lo recomienda para evitar ciertos tipos de vulnerabilidades de seguridad:

ALLOWED_HOSTS

La siguiente sección en la que nos enfocaremos es DATABASE. Gestiona el acceso a la base de datos. Por defecto, contiene la configuración para el motor de base de datos SQLite. Sin embargo, vamos a utilizar la base de datos PostgreSQL para el proyecto. Django utilizará el adaptador psycopg2 para comunicarse con PostgreSQL:

django 1

Ahora, ve al final del archivo. Agrega las siguientes líneas para indicar la ubicación de los archivos estáticos. Esto ayuda a Nginx a manejar las solicitudes de estos elementos:

static

Nuestro trabajo con settings.py ha terminado por ahora. Guarda el archivo y cierra el editor.

  • Finalizando la configuración inicial del proyecto

Ahora podemos migrar el esquema inicial de la base de datos a la base de datos PostgreSQL dedicada. Ejecuta el siguiente comando:

A continuación, necesitamos crear un superusuario para el proyecto. Para generar un superusuario, ejecuta el siguiente comando:

viktor_project

Recopila todos los archivos estáticos en la ubicación que especificamos en settings.py. Los archivos estáticos se recopilarán en un directorio separado llamado “static” dentro del directorio del proyecto:

Ahora, necesitamos hacer algunos ajustes en el firewall del servidor. Si seguiste la guía de configuración del servidor, ya tendrás UFW configurado y activado. Crearemos una excepción para el puerto 8000. Este es el puerto predeterminado que utiliza Django. Consulta esta guía para obtener más información sobre los conceptos básicos y el uso del firewall UFW.

A continuación, verifica la acción:

Finalmente, podemos probar el servidor en acción. Inicia el servidor de desarrollo de Django:

Si la configuración se realizó correctamente, el servidor de desarrollo de Django debería iniciarse y aceptar solicitudes entrantes. Abre un navegador y ve a la IP/dominio de tu servidor en el puerto 8000:

django 2

Deberías llegar a la página de inicio predeterminada de Django. Para acceder al panel de administración, añade /admin a la URL. El panel de administración solo es accesible para el superusuario que creamos previamente:

Después de iniciar sesión, llegará a la interfaz de administración predeterminada de Django:

django 3

Hemos terminado las pruebas por ahora. Para detener el servidor, presione “Ctrl + C” en la ventana de la terminal.

  • Probando Gunicorn

Antes de salir del entorno virtual, queremos asegurarnos de que Gunicorn pueda servir las aplicaciones. La forma de probarlo es usando Gunicorn para cargar el módulo WSGI del proyecto.

El comando Gunicorn se encuentra dentro del directorio del proyecto:

Esto iniciará Gunicorn en la misma interfaz en la que se estaba ejecutando Django. Podemos probar la aplicación nuevamente desde un navegador web normal. Tenga en cuenta que la interfaz de administración no tendrá ningún estilo aplicado porque Gunicorn todavía no sabe cómo encontrar los contenidos CSS estáticos:

Cuando termine, presione “Ctrl + C” en la ventana de la terminal para detener el servidor Gunicorn.

  • Salir del entorno virtual

La configuración de la aplicación Django ha finalizado. Ejecute el siguiente comando para salir del entorno virtual:

Archivos de socket y servicio de Gunicorn

Hemos verificado que Gunicorn puede interactuar con la aplicación Django. Sin embargo, necesitamos una forma más robusta de administrar el servidor de aplicaciones. Aquí entra systemd en la ecuación. Systemd es uno de los sistemas de inicio más populares disponibles en Linux. Aquí tiene una guía detallada sobre cómo administrar servicios y unidades de systemd.

Podemos crear archivos de socket y de servicio para Gunicorn para permitir que systemd lo administre como si fuera un servicio. Al arrancar, se generará el socket de Gunicorn. El socket escuchará las conexiones entrantes. Cuando se produzca una conexión, systemd iniciará los procesos de Gunicorn para manejar la conexión.

  • Socket de Gunicorn

Comencemos creando un socket de Gunicorn. El archivo debe crearse con privilegios de sudo:

Introduzca el siguiente código dentro del archivo:

Como puede ver, hay tres secciones en el código.

  • [Unit]: Esta sección describe el socket.
  • [Socket]: Define la ubicación del socket.
  • [Install]: Esta parte asegura que systemd cree el socket en el momento adecuado.

Guarde el archivo y cierre el editor.

  • Servicio de Gunicorn

A continuación, crearemos un archivo de servicio para Gunicorn. Al igual que el archivo de socket, también debe crearse con privilegios de sudo:

Introduzca el siguiente código:

El código contiene múltiples secciones:

  • [Unit]: Esta sección especifica metadatos y dependencias. También describe que se inicie solo después de que se alcance el objetivo de red.
  • [Service]: Esta sección especifica el usuario y el grupo bajo los cuales se ejecutará el proceso. La propiedad del grupo se establece en “www-data” para que Nginx pueda comunicarse con Gunicorn. También mapea los directorios de trabajo y especifica los comandos de inicio.
  • [Install]: Esta sección le indica a systemd con qué vincular este servicio si está habilitado en el arranque. Debería iniciarse después de que el sistema multiusuario normal comience a funcionar.

A continuación, guarde el archivo y cierre el editor.

  • Habilitar el socket de Gunicorn

El socket de Gunicorn está listo para usarse. Por lo tanto, puede ejecutar los siguientes comandos. Esto iniciará y habilitará el socket. El archivo del socket se creará en /run/gunicorn.sock en el arranque. Cuando se realice una conexión al socket, systemd iniciará el servicio Gunicorn para manejarla:

Verifique el estado del socket de Gunicorn:

Ahora, verifique la existencia del archivo del socket:

Si el estado de systemctl indica un error o no se encontró el archivo gunicorn.sock, esto indica que el socket no se creó correctamente. Revise el registro detallado para obtener pistas:

gunicorn.socket

No olvide volver a revisar el archivo gunicorn.socket en busca de posibles errores.

  • Activación del socket

Hemos iniciado el gunicorn.socket hasta ahora. Sin embargo, sin ninguna solicitud de conexión, gunicorn.service no se activará. A continuación, verifique el estado de Gunicorn:

Podemos probar el mecanismo de activación del socket enviando una solicitud de conexión usando curl:

Debería obtener una salida HTML de la aplicación. Esto indica que Gunicorn se inició correctamente y pudo servir la aplicación Django. Verifique el estado actual del servicio Gunicorn:

Si hay algún comportamiento o salida inesperada (que indique un error), revise los registros detallados para obtener pistas:

Si se realizaron cambios en el archivo gunicorn.service, entonces debe recargar el demonio para volver a leer la definición del servicio. También requiere reiniciar el servicio Gunicorn:

Configuración de Nginx

Ahora, configuraremos Nginx para pasar el tráfico entrante al proceso. Primero, cree un nuevo bloque de servidor en Nginx:

Luego, ingrese el siguiente código:

 

Aquí hay múltiples bloques en la configuración:

  • servicio: Este bloque define que el servidor debe escuchar normalmente en el puerto 80 y debe responder al nombre de dominio o dirección IP del servidor.
  • location: Esta es la primera entrada de ubicación. Define dónde encontrar los activos estáticos.
  • location: Esta es la segunda entrada de ubicación. Este bloque define los parámetros estándar del proxy y cómo pasar el tráfico al socket de Gunicorn.

Guarde el archivo y cierre el editor. Vincule el archivo al directorio “sites-enabled” para activarlo:

Después de eso, pruebe si hay algún error de sintaxis en la configuración de Nginx:

Si no encontró ningún error, entonces reinicie Nginx para implementar el cambio:

Necesitamos modificar las reglas de UFW nuevamente. Ya no necesitamos acceso al servidor de desarrollo, por lo que podemos eliminar la excepción para el puerto 8000. Además, queremos abrir el puerto 80 para el tráfico normal:

Verifique estos cambios en las reglas del cortafuegos:

El servidor ahora debería ser accesible desde un navegador web normal.

Procedimientos de resolución de problemas

Si todos los pasos se siguieron correctamente, la aplicación Django debería ser accesible a través de Internet. Si no es así, indica que la instalación no salió como se planeó. Necesitamos solucionar problemas para descubrir el origen del problema.

  • Nginx muestra la página predeterminada

Si Nginx muestra la página predeterminada en lugar del proxy de la aplicación, generalmente significa que el server_name se configuró incorrectamente en el bloque del servidor.

En este ejemplo, el bloque del servidor se almacena en la siguiente ubicación:

La server_name entrada determina qué bloque de servidor usará Nginx para responder a las solicitudes. Si muestra la página predeterminada, probablemente Nginx no pudo hacer coincidir la solicitud con un bloque de servidor explícito, por lo que está recurriendo al bloque predeterminado en su lugar:

Compruebe si el bloque de servidor de su proyecto Django tiene un server_name.

  • 502 Bad Gateway

El error 502 indica que Nginx no pudo realizar el proxy de la solicitud con éxito. Existe una amplia gama de posibles problemas de configuración que pueden provocar el error 502, por lo que necesitamos pistas para solucionar el problema correctamente.

La fuente principal de pistas son los registros de errores de Nginx. Generalmente, sugerirá las condiciones que causaron los problemas durante el proxy. Verifique el registro de errores de Nginx usando el siguiente comando:

Una vez que se abra el registro, intente acceder al servidor una vez más. Debería generar un nuevo mensaje de error en el registro. Esto puede ayudar a delimitar el problema. Aquí hay un par de mensajes posibles:

  • connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

Indica que Nginx no pudo encontrar gunicorn.sock en la ubicación definida en la configuración. La ubicación está descrita por la directiva proxy_pass bajo el bloque del sitio. Compruebe si proxy_pass indica la ubicación correcta de gunicorn.sock generado por la unidad systemd gunicorn.socket:

Si gunicorn.sock no se encontró bajo el directorio /run, significa que systemd no pudo generarlo. Debe volver a verificar los pasos de configuración del archivo de socket de Gunicorn.

  • connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

Indica que Nginx no pudo conectarse al socket de Gunicorn debido a problemas de permisos. Puede ocurrir si el proceso se realizó como usuario root en lugar de un usuario sudo . Aunque systemd generó gunicorn.sock con éxito, Nginx no puede usarlo.

Un posible culpable puede ser los permisos limitados entre el directorio raíz (/) y el archivo gunicorn.sock . Verifique los permisos y la propiedad del archivo de socket y de cada uno de sus directorios principales:

La primera columna describe los permisos del archivo. La segunda columna describe el usuario propietario y la tercera columna el grupo propietario. Si alguno de los directorios que conducen a gunicorn.sock no tiene los permisos de lectura y ejecución adecuados, Nginx no podrá acceder al socket.

  • Django muestra “could not connect to the server: Connection refused”

Indica que Django no pudo conectarse al servidor PostgreSQL. Asegúrese de que el servidor PostgreSQL esté funcionando:

Si no se está ejecutando, ejecute los siguientes comandos para iniciarlo y habilitarlo:

sudo systemctl enable postgresql

Si sigue teniendo este error, asegúrese de que las credenciales de la base de datos estén correctamente definidas en settings.py:

Más resolución de problemas

Para una resolución de problemas adicional, existen varios registros configurados. Estos registros pueden ayudar a acotar el origen de los problemas.

Aquí tiene una lista de registros que pueden ayudar:

  • Registros de Nginx
  • Registros de acceso-Nginx
  • Registros de errores-Nginx
  •  Registros de aplicación-Gunicorn
  •  Registros de socket-Gunicorn
Después de realizar cualquier actualización en la configuración o la aplicación, es posible que deba reiniciar los procesos para aplicar los cambios. Si se actualizó la aplicación Django, reinicie el proceso Gunicorn para aplicar los cambios:
En caso de que se realicen cambios en los archivos de servicio o socket de Gunicorn, vuelva a cargar el demonio y reinicie los procesos:
Si se realizaron cambios en la configuración del bloque de servidor de Nginx, se debe probar antes de ponerlo en acción. También requiere reiniciar Nginx:

Reflexiones finales

Esta guía demuestra con éxito cómo sentar las bases de Django. Django proporciona muchos de los componentes comunes de una aplicación web, lo que le permite concentrarse en los elementos únicos. El proyecto Django funcionará dentro del entorno virtual. Gunicorn gestiona la comunicación entre las solicitudes de los clientes y Django. Por último, Nginx actúa como un proxy inverso para manejar las conexiones de los clientes.

¡Feliz computación!

author

Hark Labs

Autor · CloudSigma

Preslav Dobrev es diseñador creativo en CloudSigma, centrado en una identidad empresarial coherente mediante el uso de canales de marketing tradicionales e innovadores. Es experto en fusionar la visión artística con el marketing estratégico para crear narrativas de marca impactantes.

Comentarios

Aún no hay comentarios. Sea el primero.