Django es un framework web de código abierto de alto nivel de Python que puede ayudarte a crear tu aplicación Python rápidamente. Fomenta el desarrollo rápido y el diseño limpio y pragmático al seguir el patrón de arquitectura modelo–plantilla–vista. De forma nativa, el framework viene con los componentes de aplicación modernos necesarios, como la autenticación de usuarios, framework de almacenamiento en caché, mapeador de objetos relacionales, despachador de URL, sistema de plantillas, e interfaz de administración personalizable.
Gunicorn ‘Green Unicorn’ es un servidor HTTP WSGI de Python para sistemas UNIX. El servidor Gunicorn es compatible con varios frameworks web, ofrece un gran rendimiento y consume pocos recursos del servidor. Docker es una plataforma de contenedores de código abierto que lleva tiempo existiendo, lo que hace que el desarrollo de aplicaciones sea rápido, eficiente y predecible.
In este tutorial, adquirirás habilidades en el desarrollo y despliegue de aplicaciones web Django contenerizadas y escalables. Utilizaremos una aplicación de Polls de Django creada siguiendo las guías introductorias para comenzar con Django. Al momento de escribir este tutorial, nos basamos en Django 3.2 compatible con Python 3.6 o posterior. Desplegaremos la aplicación como un contenedor con Docker y la serviremos con el servidor Gunicorn. Por supuesto, antes de desplegar la aplicación Django en un contenedor, tendrás que realizar algunas modificaciones en el código del proyecto para manejar aspectos como el registro en flujos de salida estándar y el trabajo con variables de entorno. Los archivos estáticos, como las imágenes CSS y JavaScript, se pueden descargar en servicios de almacenamiento de objetos para permitir una gestión sencilla de los archivos desde una única ubicación en un entorno multicontenedor.
Te mostraremos cómo implementar estas modificaciones basándonos en la bien estructurada metodología de los doce factores para crear aplicaciones web escalables. Una vez que completes las modificaciones, compilarás una imagen de Docker de la aplicación y desplegarás la aplicación contenerizada con Docker. Te recomendamos que sigas los pasos descritos en el tutorial para comprenderlo por completo.
Requisitos previos
Al ser este un tutorial práctico, te recomendamos tener la siguiente configuración para ayudarte a seguir los pasos:
-
Un servidor Ubuntu 20.04. Puedes seguir los pasos del 1 al 4 de este tutorial paso a paso para ayudarte a configurar tu servidor Ubuntu en CloudSigma.
-
Asegúrate de añadir un usuario con privilegios de sudo en ambos nodos que utilizaremos para ejecutar los comandos como se describe en el tutorial anterior.
-
Instala Docker en el servidor. Puedes seguir los pasos 1, 2 y 3 de nuestro tutorial sobre cómo instalar y operar Docker. Recuerda añadir al usuario sudo creado anteriormente al grupo Docker.
-
Un espacio de almacenamiento de objetos compatible. Django admite varios servicios de almacenamiento, como se indica en la documentación de django-storages. Puedes elegir el que prefieras y seguir la documentación para configurarlo. Para este tutorial, utilizaremos MinIO que es un servicio de almacenamiento en la nube compatible con S3.
-
Una instancia de base de datos SQL. Django admite varias bases de datos SQL que eres libre de elegir. Para este tutorial, utilizaremos PostgreSQL. La base de datos PostgreSQL no se desplegará dentro de un contenedor. Configuraremos un servidor Ubuntu independiente para alojar la instancia de PostgreSQL para asegurarnos de lograr nuestra configuración multicontenedor, así como la persistencia de datos. Puedes crear otra instancia de Ubuntu 20.04 y seguir este tutorial para Configurar una instancia de base de datos PostgreSQL en Ubuntu. Recuerda añadir un rol en la base de datos PostgreSQL para tu usuario sudo como se explica en los Pasos 2 y 3. Este rol te permitirá conectarte a la base de datos desde los otros servidores que alojan tus contenedores.
De acuerdo con estos requisitos previos, deberías tener dos instancias de servidor Ubuntu. Una instancia ejecutará tu contenedor Docker y la otra ejecutará la instancia de PostgreSQL. ¡Comencemos!
Paso 1: Configuración de la instancia de la base de datos PostgreSQL
En esta sección, modificaremos las configuraciones de Postgres en el servidor Ubuntu que ejecuta la instancia de Postgres. Esto permitirá conexiones desde una dirección IP externa. Una vez que se conecte, podremos crear una base de datos y un rol de usuario, específicos para la aplicación Django Polls que estamos implementando.
Primero, si configuró su entorno según los Requisitos previos, debería tener un rol en su base de datos PostgreSQL para su usuario sudo. A continuación, debemos establecer una contraseña para este rol. Mientras esté en el servidor que ejecuta PostgreSQL, inicie sesión en la terminal de Postgres con el siguiente comando:
|
1 |
sudo -u postgres psql |
Una vez en la terminal de Postgres, ejecute el comando \password para alterar la contraseña de un usuario. La sintaxis para el comando \password es \password <nombre_usuario>. Para nuestro caso, el comando:
|
1 |
\password cloudsigma |
Introduzca la contraseña y confírmela. Guarde esta contraseña en un lugar seguro, ya que la utilizará para autenticarse desde el otro servidor Ubuntu más adelante. Después de eso, escriba exit y presione Enter para salir de la terminal de Postgres.
Si había habilitado el cortafuegos (ufw) en la instancia del servidor PostgreSQL, deberá permitir el tráfico al puerto predeterminado de Postgres 5432. Puede restringir el tráfico para que solo se origine desde una dirección IP específica de su otro servidor Ubuntu que ejecutará el contenedor Docker. Ejecute el siguiente comando para agregar la regla ufw, reemplazando su dirección IP donde se destaca:
|
1 |
sudo ufw allow from ubuntu_server_ip_address to any port 5432 |
Esto garantizará que solo su servidor pueda conectarse a la instancia de PostgreSQL. Si bien eso permite el tráfico a través del cortafuegos, también debe modificar los archivos de configuración de PostgreSQL para permitir la conexión desde la dirección IP remota. Por defecto, la configuración solo permite la conexión desde localhost. Los archivos de configuración de PostgreSQL se encuentran en el directorio /etc/postgresql/12/main . 12, en este caso, es la versión de PostgreSQL que instalamos para este tutorial. Es posible que haya instalado una versión diferente. Por lo tanto, puede cambiar al directorio /etc/postgresql/ y listar el contenido para encontrar el número de versión de PostgreSQL que instaló.
Use nano para modificar el archivo de configuración:
|
1 |
sudo nano /etc/postgresql/12/main/postgresql.conf |
Busque esta línea a continuación, descoméntela y configúrela para permitir conexiones desde todas las direcciones IP:
|
1 |
listen_addresses = '*' |
Guarde y cierre el archivo. Luego, tiene que editar el archivo pg_hba.conf también, está en el mismo directorio que postgresql.conf. El archivo pg_hba.conf le permite definir desde qué computadoras puede conectarse a la instancia de PostgreSQL, así como el método de autenticación. Abra el archivo con nano:
|
1 |
sudo nano /etc/postgresql/12/main/pg_hba.conf |
Lea los comentarios en este archivo para comprender las palabras clave. La sección que estamos buscando es esta:

Nos centraremos en la segunda línea, querrá que se vea como la línea de abajo después de descomentarla:
|
1 |
host all all your_ubuntu_server_ip/24 md5 |
Reemplace la parte destacada con la dirección IP de su servidor Ubuntu para permitir que se conecte a la instancia de PostgreSQL. Guarde el archivo una vez que esté listo. Reinicie la base de datos PostgreSQL para que los cambios surtan efecto:
|
1 |
sudo service postgresql restart |
Nuestro otro servidor Ubuntu con la dirección IP especificada debería poder conectarse a la instancia de Postgres.
Paso 2: Conectarse a la instancia del servidor PostgreSQL y crear una base de datos y un usuario
En este paso, intentaremos asegurarnos de que la instancia de Ubuntu que sirve a nuestro contenedor Docker pueda conectarse al otro servidor que ejecuta la instancia de PostgreSQL. Inicie sesión en la instancia de Ubuntu que tiene Docker e instale el paquete postgresql-client dentro de la máquina host de Ubuntu (todavía no dentro del contenedor).
Como norma, primero actualice el paquete apt y luego instale el paquete con los siguientes comandos:
|
1 |
sudo apt update |
|
1 |
sudo apt install postgresql-client |
El paquete instalado arriba le ayudará a crear una base de datos y un usuario para su aplicación. A continuación, debemos conectarnos a la instancia de PostgreSQL emitiendo parámetros de conexión al cliente de Postgresql.
Los parámetros de conexión siguen esta sintaxis:
|
1 |
psql -U username -h host -p port -d database --set=sslmode=require |
En este comando, el username es el usuario/rol que agregó a su base de datos PostgreSQL. host es la dirección IP de la instancia de Ubuntu que ejecuta su base de datos PostgreSQL. port es el puerto predeterminado en el que Postgres escucha las conexiones entrantes, es decir, 5432. En el lugar de la database, utilizaremos la base de datos predeterminada llamada postgres que viene con la instalación de PostgreSQL. Reemplace sus valores en las partes resaltadas de manera adecuada y presione Enter. Cuando se le solicite, ingrese la contraseña que había establecido. Esto lo iniciará en el prompt de Postgres donde puede administrar la base de datos.
Se ha conectado correctamente a la instancia de PostgreSQL. Ahora puede crear una base de datos para la aplicación de encuestas de Django. Llamémosla django_polls:
|
1 |
CREATE DATABASE django_polls; |
Asegúrese de que su instrucción termine con un punto y coma para evitar errores. Luego, cambie a la base de datos django_polls con el comando:
|
1 |
\c django_polls; |
A continuación, cree un usuario de base de datos específico para este proyecto. Nombremos al usuario django_user:
|
1 |
CREATE USER django_user WITH PASSWORD 'password'; |
Elija una contraseña segura para su usuario. Once done, we need to modify the connection parameters for the user we just created. This helps speed up database operations by ensuring the correct values are not queried and set each time a connection is established.
Establezca la codificación predeterminada que Django espera como UTF-8:
|
1 |
ALTER ROLE django_user SET client_encoding TO 'utf8'; |
A continuación, establezca el esquema de aislamiento de transacciones predeterminado en “ read committed”, que bloquea las lecturas de transacciones no confirmadas:
|
1 |
ALTER ROLE django_user SET default_transaction_isolation TO 'read committed'; |
Establezca su zona horaria. Para mantener el tutorial universal, utilizaremos UTC:
|
1 |
ALTER ROLE django_user SET timezone TO 'UTC'; |
Por último, otorgue privilegios administrativos de la base de datos al nuevo usuario:
|
1 |
GRANT ALL PRIVILEGES ON DATABASE django_polls TO django_user; |
Salga del prompt de PostgreSQL cuando esté listo:
|
1 |
\q |
Eso es todo para este paso. Una vez que configure correctamente su aplicación Django, debería poder administrar su base de datos.
Paso 3: Obtener la aplicación desde un repositorio de Git y definir las dependencias
En este paso, clonaremos el repositorio de la aplicación Django-polls. Este repositorio contiene el código para el tutorial de Django’s escribir su primera aplicación de Django.
Inicie sesión en el servidor Ubuntu que ejecuta Docker, cree un directorio llamado django_project y navegue dentro de él:
|
1 2 |
mkdir django_project cd django_project |
Luego, clone el repositorio en el directorio con el siguiente comando:
|
1 |
git clone https://github.com/jaymoh/django-polls.git |
Navegue dentro del directorio y enumere el contenido:
|
1 |
cd django-polls |
Enumere el contenido del directorio:
|
1 |
ls |

Observe los siguientes elementos:
-
manage.py: este archivo es la entrada a la utilidad de línea de comandos que ofrece Django para administrar su aplicación.
-
mysite: un directorio con el alcance del proyecto Django y la configuración del código.
-
polls: un directorio que contiene el código de la aplicación polls .
-
templates: contiene archivos de plantilla personalizados para las páginas de administración.
Para obtener más información sobre cómo creamos realmente el proyecto, consulte Escribir su primera aplicación de Django de la documentación oficial. Dentro del django-polls directorio, queremos tener nuestras dependencias de Python definidas en un archivo de texto. Lo llamaremos requirements.txt. Abra el archivo con su editor preferido:
|
1 |
nano requirements.txt |
Pegue las siguientes líneas dentro del archivo para declarar las dependencias:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Django==3.2.9 gunicorn==20.1.0 docutils==0.18.1 sqlparse==0.4.2 jmespath==0.10.0 psycopg2==2.9.2 python-dateutil==2.8.2 pytz==2021.3 six==1.16.0 urllib3==1.26.7 django-storages==1.12.2 minio==7.1.6 django-minio-backend==3.3.2 django-dotenv==1.4.2 boto3==1.21.38 |
En este archivo, hemos definido las dependencias de Python con sus versiones exactas que deben instalarse al compilar la aplicación. Algunas de ellas incluyen Django, django-storages para interactuar con buckets de almacenamiento de objetos, el psycopg2 adaptador para PostgreSQL, gunicorn servidor WSGI y otras dependencias adicionales. Guarde y cierre el archivo cuando termine.
Paso 4: Configuración de variables de entorno para una aplicación Django
La twelve-factor app metodología recomienda extraer las configuraciones codificadas de forma rígida del código base de su aplicación. Al hacerlo, obtiene la libertad de cambiar el comportamiento de la aplicación en tiempo de ejecución modificando las variables de entorno sin tocar el código base. Docker funciona con esta configuración, por lo que modificaremos el archivo de configuración para que funcione con variables de entorno. Kubernetes también funciona con esta configuración. Compartiremos otro tutorial sobre el despliegue con Kubernetes en el CloudSigma blog.
El settings.py es el archivo de configuración principal para un proyecto de Django. Es un módulo de Python que utiliza estructuras de datos nativas para configurar la aplicación. Para nuestra aplicación, el archivo se encuentra en la ubicación django-polls/mysite/settings.py. La mayoría de sus valores están codificados de forma rígida. Esto requerirá que modifique el archivo de configuración en el código base si cambia el comportamiento de la aplicación. Queremos cambiar eso. Afortunadamente, Python ofrece la función getenv en el módulo os . Podemos usarlo para configurar Django para que lea los parámetros de configuración de las variables de entorno locales en su lugar.
Continuemos modificando el archivo django-polls/mysite/settings.py para reemplazar los valores codificados de forma rígida de las variables que queramos actualizar en tiempo de ejecución con una llamada a os.getenv. Esta función lee el valor establecido en el nombre de la variable de entorno proporcionado. Opcionalmente, puede proporcionar un segundo parámetro que es un valor predeterminado que se utilizará si la variable de entorno no está establecida.
Aquí hay un ejemplo:
|
1 |
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') |
En la línea anterior, le decimos a Django que recupere la clave secreta de la variable de entorno. No proporcionamos un valor alternativo ya que proporcionaremos la clave externamente. Si no existe, la aplicación no debería iniciarse. Al proporcionar la clave secreta externamente, también queremos asegurarnos de que todas nuestras copias en contenedores de la aplicación utilicen la misma clave en los distintos servidores. Esto evita posibles problemas que surgen cuando las distintas copias de la aplicación utilizan claves diferentes.
Aquí hay otro ejemplo con una opción predeterminada:
|
1 |
DEBUG = os.getenv('DEBUG', False) |
En esta línea, definimos una variable de entorno DEBUG que debe leerse. Sin embargo, si no está establecida, hemos proporcionado un segundo parámetro que se pasará a la variable de configuración DEBUG. DEBUG se establece en False para garantizar que no se pase información confidencial al frontend en caso de que haya un problema con la aplicación. Sin embargo, si estamos en modo de desarrollo, queremos que se establezca en True para permitirnos ver la información del error y facilitarnos la corrección de errores.
Ahora que conoce la importancia de las variables de entorno, abra el archivo django_project/django-polls/settings.py en su editor. Primero, importe el módulo os agregando esta línea en la parte superior del archivo settings.py:
|
1 |
import os |
A continuación, busque estas variables y actualícelas de la siguiente manera:
|
1 2 3 |
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') DEBUG = os.getenv('DEBUG', False) ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') |
En la configuración ALLOWED_HOSTS, especificamos que debe obtener el valor de la variable de entorno DJANGO_ALLOWED_HOSTS, y dividirlo en una Python list utilizando la coma ( ,) como separador. Si la variable no está presente, ALLOWED_HOSTS se establece en 127.0.0.1.
A continuación, desplácese por el archivo y busque la sección DATABASES, configúrela para que también lea de las variables de entorno:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.{}'.format( os.getenv('DB_ENGINE', 'sqlite3') ), 'NAME': os.getenv('DB_DATABASE', 'django_polls'), 'USER': os.getenv('DB_USERNAME', 'your_db_username'), 'PASSWORD': os.getenv('DB_PASSWORD', 'your_secure_default_password'), 'HOST': os.getenv('DB_HOST', '127.0.0.1'), 'PORT': os.getenv('DB_PORT', 5432), 'OPTIONS': json.loads( os.getenv('DB_OPTIONS', '{}') ), } } |
Observe que hemos agregado el módulo json.loads. También debe agregar una importación del módulo en la parte superior del archivo settings.py:
|
1 |
import json |
La función json.loads deserializa un objeto JSON pasado a DATABASES['default']['OPTIONS'] desde la variable de entorno DB_OPTIONS. Especificar esta opción nos permite pasar una estructura de datos arbitraria para definir la configuración de la base de datos. Un motor de base de datos incluye un conjunto de opciones válidas aplicables a él. La opción JSON nos brinda la flexibilidad de codificar un objeto JSON con los parámetros adecuados para el motor de base de datos que estemos utilizando en ese momento.
La opción DATABASES['default']['NAME'] especifica el nombre de la base de datos en el sistema de gestión de bases de datos relacionales que hemos configurado. En el caso de utilizar una base de datos SQLite, debe especificar la ruta al archivo de la base de datos.
Tenga en cuenta que Python ofrece varios métodos para read external environment variables. Solo hemos utilizado uno de ellos. Es libre de investigar y utilizar otros métodos. En este paso, ha aprendido a trabajar con variables de entorno externas. Esto le brinda la flexibilidad de cambiar las variables y alterar el comportamiento de la aplicación que se ejecuta en contenedores. En el siguiente paso, aprenderá a trabajar con servicios de almacenamiento de objetos.
Paso 5: Trabajo con servicios externos de almacenamiento de objetos
Una de las principales ventajas de contenerizar su aplicación es hacerla portátil para facilitar la implementación de varias copias de la aplicación cuando aumenta el tráfico. Por lo tanto, da margen para el escalado. Sin embargo, esto plantea el problema de mantener las versiones de los archivos estáticos y recursos a través de varios contenedores. Gracias a las mejoras en la tecnología en la nube, puede descargar estos elementos estáticos compartidos en un almacenamiento externo. Luego, puede hacer que los archivos sean accesibles a través de una red para todos sus contenedores en ejecución. En lugar de intentar sincronizar los archivos entre los distintos contenedores en ejecución, tiene un lugar centralizado para administrarlos.
El concepto que intentamos explicar anteriormente es el uso de servicios de almacenamiento de objetos en la nube, o Simple Storage Services (S3). Django tiene un paquete llamado django-storages que te permite trabajar con backends de almacenamiento remoto. Django-storages funciona con la mayoría de los servicios de almacenamiento de objetos compatibles con S3, como FTP, SFTP, AWS S3 de Amazon, Google Cloud Storage, Dropbox y Azure Storage, entre otros. En este tutorial, utilizaremos MinIO. No dudes en utilizar cualquier otro servicios de almacenamiento de objetos compatibles con S3. MinIO ofrece almacenamiento de objetos de alto rendimiento compatible con S3. Con MinIO, puedes crear una infraestructura de datos compatible con S3 en cualquier nube.
Te mostraremos cómo configurar un servicio de almacenamiento MinIO en la plataforma CloudSigma. Por favor, sigue estos pasos:
-
Comienza por crear una cuenta en CloudSigma. Si tienes algún problema al crear el almacenamiento MinIO, ponte en contacto con el soporte de chat en vivo gratuito 24/7 de CloudSigma, y ellos te ayudarán.
-
Añade tu información de facturación.
-
A continuación, solicita tu bucket de acceso público desde aquí: https://blog.cloudsigma.com/xxxx. Deberás ponerte en contacto con el soporte de chat en vivo para obtener las credenciales de acceso a tu cuenta.
-
Una vez que se haya creado tu entorno de almacenamiento de objetos MinIO, se te proporcionarán las credenciales de acceso y otras instrucciones para acceder a él. Las credenciales deben incluir tu MINI_ACCESS_KEY, MINIO_SECRET_KEY, y MINIO_URL. Utilizarás estas claves en las instrucciones a continuación.
Hagamos algunos cambios más en el archivo mysite/settings.py que hemos estado modificando en el paso anterior. En el archivo, añade la aplicación storages a la lista de Django de INSTALLED_APPS:

La aplicación storages se instala a través de django-storages como se define en el requirements.txt. Desplázate hasta la parte inferior del archivo y reemplaza la variable STATIC_URL con el siguiente fragmento de código:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# Archivos estáticos (CSS, JavaScript, Imágenes) # https://docs.djangoproject.com/en/3.2/howto/static-files/ DEFAULT_FILE_STORAGE = os.getenv('STATIC_DEFAULT_FILE_STORAGE', 'storages.backends.s3boto3.S3Boto3Storage') AWS_S3_ENDPOINT_URL = os.getenv('MINIO_URL') AWS_ACCESS_KEY_ID = os.getenv('MINIO_ACCESS_KEY') AWS_SECRET_ACCESS_KEY = os.getenv('MINIO_SECRET_KEY') AWS_STORAGE_BUCKET_NAME = os.getenv('STATIC_MINIO_BUCKET_NAME') AWS_S3_OBJECT_PARAMETERS = { 'CacheControl': 'max-age=86400', } AWS_LOCATION = 'static' AWS_DEFAULT_ACL = 'public-read' STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' STATIC_URL = '{}/{}/'.format(AWS_S3_ENDPOINT_URL, AWS_LOCATION) STATIC_ROOT = "static/" |
Ten en cuenta que algunas de las variables de configuración están codificadas de forma fija:
-
STATICFILES_STORAGE: define el backend de almacenamiento que Django utilizará para manejar archivos estáticos. En nuestra guía, estamos utilizando el almacenamiento MinIO, pero puedes usar cualquier backend compatible con S3 como se explica en la documentación de Django Storages.
-
AWS_S3_OBJECT_PARAMETERS: define las cabeceras de control de caché (cache-control).
-
AWS_LOCATION: usamos esto para establecer un directorio dentro del bucket de almacenamiento donde se guardarán todos los archivos estáticos. Eres libre de elegir un nombre diferente.
-
AWS_DEFAULT_ACL: establece la lista de control de acceso (ACL) para los archivos estáticos. Establecer el valor en ‘ public-Read’ hará que los archivos sean accesibles para todos los usuarios públicos.
-
STATIC_URL: Django utiliza la URL base establecida en esta variable para generar URLs para archivos estáticos. La URL base en este caso se deriva de combinar la URL del endpoint y el subdirectorio de archivos estáticos.
-
STATIC_ROOT: define dónde recopilar los archivos estáticos localmente antes de copiarlos al almacenamiento de objetos remoto.
También tenemos algunas variables de entorno definidas externamente para mantener la flexibilidad y la portabilidad:
-
AWS_STORAGE_BUCKET_NAME: define el nombre del bucket de almacenamiento al que Django subirá los recursos.
-
AWS_S3_ENDPOINT_URL: define la URL del endpoint utilizada para acceder al servicio de almacenamiento de objetos. Esta será la URL mapeada al servidor que aloja su servicio MinIO.
Guarde y cierre el archivo cuando haya terminado de editar.
Una vez que tenga esa configuración en su lugar y haya instalado las dependencias de Python declaradas, puede ejecutar el comando de Django manage.py collectstatic en cualquier momento para recopilar los archivos estáticos de su proyecto y subirlos al backend de almacenamiento de objetos remoto:
|
1 |
python manage.py collectstatic |
Sin embargo, aún no hemos configurado el archivo env con las configuraciones, por lo que probablemente fallará.
Cuando ejecuta el comando, toma un momento copiar sus recursos a MinIO Cloud Storage, dependiendo de su tamaño y de su velocidad de internet.
Eso es todo para este paso. Veamos cómo podemos manejar el envío de registros de Django al Docker Engine para que pueda verlos usando el comando docker logs en el siguiente paso.
Paso 6: Configuración del registro en una aplicación Django
Mientras está en modo de depuración, cuando la opción DEBUG está establecida en True, Django registra información en la salida estándar y en el error estándar. La información de registro generalmente aparece en la terminal desde la cual inició el servidor HTTP de desarrollo.
Mientras está en producción, es probable que esté utilizando un servidor HTTP diferente, y la opción DEBUG está establecida en False. Django utilizará un método de registro diferente en este caso. Django envía registros de prioridad ERROR o CRITICAL a una cuenta de correo electrónico administrativa que usted defina. Esto funciona muy bien para muchas situaciones.
En configuraciones contenedorizadas y de Kubernetes, se recomienda encarecidamente registrar en la salida estándar y en el error estándar. Los mensajes de registro se recopilan en un solo directorio en el sistema de archivos del nodo y son fácilmente accesibles utilizando los comandos kubectl y docker . Con un punto de registro centralizado en el sistema de archivos del nodo, el equipo de operaciones puede ejecutar fácilmente procesos en cada nodo para monitorear y reenviar registros. Por lo tanto, debemos configurar nuestra aplicación para escribir registros en esta configuración estándar.
Le alegrará saber que Django aprovecha el módulo logging altamente personalizable de la biblioteca estándar de Python. Esto le permite definir un diccionario que se pasa a logging.config.dictConfig para definir las salidas y el formato deseados. Aquí hay un buen artículo sobre Django Logging, The Right Way que puede ayudarle a dominar las técnicas de registro en Django.
Abra el archivo django-polls/mysite/settings.py en su editor. Agregue una importación para la biblioteca logging.config de Python en la parte superior del archivo:
|
1 |
import logging.config |
Hasta ahora, con todas las importaciones que hemos agregado, su sección de importaciones en settings.py debería verse así:

La biblioteca logging.config recibe un diccionario de nueva configuración de registro a través de la función dictConfig para anular el comportamiento de registro predeterminado de Django.
Desplácese hasta la parte inferior del archivo y agregue el siguiente fragmento de código de configuración de registro:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# Configuración de registro # Desactivar configuración anterior LOGGING_CONFIG = None # Obtener nivel de registro del entorno LOGLEVEL = os.getenv('DJANGO_LOGLEVEL', 'info').upper() logging.config.dictConfig({ 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'console': { 'format': '%(asctime)s %(levelname)s [%(name)s:%(lineno)s] %(module)s %(process)d %(thread)d %(message)s', }, }, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'formatter': 'console', }, }, 'loggers': { '': { 'level': LOGLEVEL, 'handlers': ['console',], }, }, }) |
LOGGING_CONFIG se establece en None para deshabilitar/limpiar las configuraciones de registro predeterminadas que define Django. LOGLEVEL se establece mediante la DJANGO_LOGLEVEL variable de entorno. Sin embargo, si no existe, queremos que se establezca en ‘ info’.
El módulo logging.config que importamos al principio proporciona una función dictConfig que se utiliza para establecer un nuevo diccionario de configuración. El diccionario define el formato de texto utilizando la clave formatters key. La salida se establece con la clave handlers key, y finalmente, la clave loggers define qué mensaje debe ir a qué manejador.
Una vez que tengas definidas esas configuraciones, Docker expondrá los registros a través del comando docker logs . De manera similar, en otro tutorial que haremos para Kubernetes, puedes ver los registros con el comando kubectl logs . Comencemos ahora el proceso de contenedorización en el siguiente paso.
Paso 7: Definición del Dockerfile de la aplicación
En este paso, definimos la configuración para levantar la imagen del contenedor que ejecutará la aplicación Django servida por el servidor WSGI Guincorn. Definiremos el entorno de ejecución para compilar una imagen de contenedor, instalaremos la aplicación y sus dependencias, y realizaremos algunas configuraciones finales.
-
La imagen base para una aplicación Django
Decidir la imagen base sobre la cual fundamentar tu contenedor es la primera decisión que tomarás al trabajar con despliegues contenedorizados. Por supuesto, tienes la opción de compilar tus imágenes de contenedor desde SCRATCH, es decir, un sistema de archivos vacío, o basarlas en una imagen de contenedor existente. Como no queremos reinventar la rueda, compilaremos nuestra imagen a partir de una imagen base. Hay muchas imágenes de contenedor de código abierto disponibles en el repositorio oficial de imágenes de contenedor de Docker. A menos que estés compilando tu imagen desde cero, se recomienda encarecidamente que utilices una imagen del hub oficial de Docker. Esto se debe a que Docker verifica que las imágenes sigan las mejores prácticas y garantiza que se apliquen actualizaciones periódicas y parches de seguridad.
Como Django es un framework de Python, aprovecharemos una imagen con un entorno estándar de Python que ya tiene instaladas las herramientas y bibliotecas que necesitamos. Desde la página oficial de imágenes de Python en Docker Hub, puedes encontrar una imagen basada en Python para varias versiones de Python.
En nuestros diversos tutoriales basados en Docker, notarás que utilizamos imágenes basadas en Alpine LinuxAlpine Linux ofrece un entorno de sistema operativo robusto pero ligero para ejecutar aplicaciones contenedorizadas. Aunque su sistema de archivos es pequeño, es extensible y viene con un sistema completo de gestión de paquetes con la posibilidad de añadir funcionalidades.
Al elegir una imagen base en Docker Hub, es posible que notes múltiples etiquetas disponibles para cada imagen. En el caso de Python, tenemos 3-alpine, que apunta a la imagen de la última versión de Python 3 de la última versión de Alpine. Esto significa que, en caso de que tu proyecto funcione con una versión de imagen anterior, podría fallar cuando los mantenedores de la imagen de Docker realicen una actualización. Para evitar este tipo de escenarios en el futuro, siempre se recomienda elegir las etiquetas más específicas para la imagen que deseas utilizar.
En este tutorial, utilizaremos la 3.8.12-alpine3.15 como imagen base para nuestra aplicación Django. Esta etiqueta específica se especificará en el Dockerfile usando la FROM instrucción. El Dockerfile estará en el directorio principal del proyecto: django_project.
Comience saliendo del directorio Django-polls para volver al directorio django_project directorio:
|
1 |
cd .. |
Una vez en el directorio, use su editor favorito para abrir un archivo llamado Dockerfile :
|
1 |
nano Dockerfile |
A continuación, pegue la siguiente línea para establecer la base de su imagen:
|
1 |
FROM python:3.8.12-alpine3.15 |
La FROM palabra clave define el punto de partida de una imagen Docker personalizada. Con eso definido, podemos continuar agregando instrucciones para configurar las aplicaciones. Estas instrucciones instalarán las dependencias necesarias, copiarán los archivos de la aplicación y configurarán el entorno de ejecución.
Add the following code snippet inside the Dockerfile:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
ADD django-polls/requirements.txt /app/requirements.txt RUN set -ex \ && apk add --no-cache --virtual .build-deps postgresql-dev build-base \ && python -m venv /env \ && /env/bin/pip install --upgrade pip \ && /env/bin/pip install --no-cache-dir -r /app/requirements.txt \ && runDeps="$(scanelf --needed --nobanner --recursive /env \ | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ | sort -u \ | xargs -r apk info --installed \ | sort -u)" \ && apk add --virtual rundeps $runDeps \ && apk del .build-deps ADD django-polls /app WORKDIR /app ENV VIRTUAL_ENV /env ENV PATH /env/bin:$PATH EXPOSE 8000 |
En este fragmento de código, le decimos a Docker que copie el archivo requirements.txt a /app/requirements.txt para garantizar que las dependencias de la aplicación estén disponibles en el sistema de archivos de la imagen. Los requisitos incluyen todos los paquetes de Python necesarios para ejecutar la aplicación. Las dependencias se copian primero para que Docker pueda almacenar en caché la capa de la imagen. Esto se debe a que Docker almacena en caché cada paso del Dockerfile. La primera compilación de la imagen suele ser más larga. Docker descargará las dependencias y luego las almacenará en caché. Si el archivo requirements.txt no cambia, Docker compilará desde la caché, lo que acelerará las compilaciones posteriores.
El siguiente paso tiene la instrucción RUN que ejecuta una lista de comandos de Linux, encadenados con el operador de Linux &&. Los comandos hacen lo siguiente:
-
Usar la herramienta de gestión de paquetes apk de Alpine para instalar los archivos de desarrollo de PostgreSQL y las dependencias básicas de compilación.
-
Crear un entorno virtual de Python.
-
Instalar las dependencias de Python según lo definido en el archivo requirements.txt utilizando pip.
-
Compilar los paquetes de tiempo de ejecución necesarios analizando los requisitos de los paquetes de Python instalados.
-
Eliminar cualquier dependencia de compilación que ya no sea necesaria.
La razón detrás de encadenar los comandos en el paso RUN es reducir las capas de la imagen. Docker crea una nueva capa de imagen sobre el sistema de archivos existente cada vez que encuentra ADD, COPY, o RUN instrucción en el Dockerfile. Comprimir los comandos donde sea aplicable minimizará el número de capas de imagen creadas.
Los elementos agregados a las capas de imagen no se pueden eliminar en una capa posterior. Debe declarar instrucciones para eliminar los elementos no deseados antes de pasar a la siguiente instrucción. Esto es necesario para reducir el tamaño de la imagen. Debería notar que agregamos el apk del comando al final de la RUN comando. Eso se hizo para eliminar las dependencias de compilación después de haberlas usado para compilar los paquetes de la aplicación.
A continuación, tenemos otra ADD instrucción que usamos para copiar el código de la aplicación al directorio /app . Luego, usaremos la instrucción WORKDIR para establecer el directorio de trabajo de la imagen en el directorio /app , que ahora tiene el código de la aplicación.
A continuación, tenemos las instrucciones ENV que usamos para establecer dos variables de entorno que la imagen pondrá a disposición de los contenedores en ejecución. Primero, establecemos la variable VIRTUAL_ENV en /env. Segundo, establecemos la variable PATH para incluir el directorio /env/bin . En estas dos líneas, estamos cargando el script /env/bin/activate , que es cómo activamos un entorno virtual en un entorno Linux. Puede leer más sobre cómo trabajar con entornos virtuales en Python en otros sistemas operativos. La última instrucción es el comando EXPOSE que establece el puerto 8000 en el que el contenedor escuchará en tiempo de ejecución.
A estas alturas, su Dockerfile está casi completo, aparte del comando predeterminado que se ejecutará cuando inicie los contenedores. Definámoslo en la siguiente sección.
-
Entendiendo el comando predeterminado de la imagen de Docker
Al iniciar un contenedor Docker, puede proporcionar un comando para ejecutar. Sin embargo, si no proporciona un comando, el comando predeterminado de la imagen de Docker determinará qué sucederá cuando se inicie el contenedor. Usamos las instrucciones ENTRYPOINT o CMD de forma individual o conjunta para definir un comando predeterminado dentro del Dockerfile.
Si elige definir tanto ENTRYPOINT como CMD, en la instrucción ENTRYPOINT, define el ejecutable que ejecutará el contenedor. En la instrucción CMD, define la lista de argumentos predeterminada para el comando ejecutable. Puede anular la lista de argumentos predeterminada agregando argumentos alternativos en la línea de comandos al iniciar el contenedor en el formato:
|
1 |
docker run <image> <arguments> |
Este formato evita que los desarrolladores anulen fácilmente el comando ENTRYPOINT . El comando ENTRYPOINT está definido para llamar a un script que configurará el entorno y realizará diferentes acciones según la lista de argumentos proporcionada.
Puede usar la instrucción ENTRYPOINT sola para configurar el ejecutable del contenedor. Sin embargo, este formato no permite definir una lista de argumentos predeterminada. Puede proporcionar argumentos cuando ejecuta el contenedor con el comando docker run .
Si elige ir solo con CMD , Docker lo interpreta como el comando y la lista de argumentos predeterminados, que puede anular en tiempo de ejecución. Puede encontrar más información en los documentos de referencia oficiales de Dockerfile.
Veamos cómo podemos aplicar la información que ha aprendido sobre los comandos predeterminados a nuestro ejemplo de contenedor. Queremos servir la aplicación de forma predeterminada utilizando el servidor gunicorn . Aunque la lista de argumentos pasada al servidor gunicorn no tiene que ser configurable en tiempo de ejecución, queremos la flexibilidad de ejecutar otros comandos para fines como la depuración o la gestión de configuraciones (inicializar la base de datos, recopilar activos estáticos, etc.). Como puede ver, nos conviene usar CMD para definir un comando predeterminado que nos permita anularlo cuando sea necesario.
Aquí hay algunas sintaxis que puede usar para definir el comando CMD :
- CMD ["command", "argument 1", "argument 2", . . . ,"argument n"]: El formato exec (formato recomendado), toma un comando y una lista de argumentos. Ejecuta el comando directamente sin procesamiento de shell.
- CMD command "argument 1" "argument 2" . . . "argumento n": El formato de shell define un comando y una lista de argumentos. Pasa la lista de comandos al shell para su procesamiento. Esto puede resultarle útil si desea sustituir variables de entorno en un comando; sin embargo, no es del todo predecible.
- CMD ["argumento 1", "argumento 2", . . . ,"argumento n"]: El formato de lista de argumentos, solo define la lista de argumentos predeterminada y se utiliza junto con una ENTRYPOINT instrucción.
Utilizaremos el exec formato para definir nuestra instrucción final en el Dockerfile. Agregue la siguiente línea al final de su Dockerfile:
|
1 |
CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "mysite.wsgi:application"] |
Ahora puede guardar y cerrar el Dockerfile.
Cuando inicie contenedores usando esta imagen, ejecutarán gunicorn vinculado al puerto de localhost 8000 con 3 workers, y llamarán a la función application en el archivo wsgi.py que se encuentra en el directorio mysite . Puede optar por proporcionar un comando diferente para invalidar el comando predeterminado en tiempo de ejecución y ejecutar un proceso diferente en lugar de gunicorn. Es posible que desee obtener más información sobre workers de Gunicorn.
Su Dockerfile ya está listo y puede usar docker build para construir la imagen de la aplicación. Puede usar docker run para iniciar el contenedor en su máquina de desarrollo local.
-
Construcción de la imagen de Docker
El comando docker build buscará un Dockerfile en el directorio actual de forma predeterminada para encontrar sus instrucciones de construcción. También envía el “contexto” de construcción al demonio de Docker. Un contexto de construcción es un conjunto de archivos que deben estar disponibles durante el proceso de construcción. De forma predeterminada, el directorio actual en el que está ejecutando el comando docker build está configurado como el contexto de construcción.
Mientras se encuentra en el mismo directorio que contiene su Dockerfile, ejecute el comando docker build. Proporcione una imagen y una etiqueta con la bandera -t y establezca el directorio actual como contexto de construcción usando el punto ( .) al final del comando:
|
1 |
docker build -t django-polls:v1 . |
En este comando, hemos nombrado a la imagen django-polls y a la etiqueta v1. Observe el punto al final del comando, lo usamos para denotar el directorio actual como el contexto de construcción.
Cuando finalice docker build , debería ver algo similar a la siguiente salida:

Su Docker image ya está lista. Si no hubiéramos desplazado algunas de las configuraciones a variables de entorno externas, podría ejecutar fácilmente su contenedor con el comando docker run . Sin embargo, dado que no hemos configurado las variables de entorno externas que establecimos en el archivo settings.py , la ejecución fallará. Finalicemos eso en el siguiente paso.
Paso 8: Configuración del entorno de ejecución y prueba de la aplicación
Nos estamos acercando al final de este tutorial. En este paso, configuraremos las variables de entorno en el archivo env . Con las variables del archivo env en su lugar, podemos crear el esquema de la base de datos, generar y cargar los archivos estáticos en el servicio de almacenamiento de objetos externo y, finalmente, probar la aplicación.
Docker viene con varios métodos que puede usar para proporcionar variables de entorno al contenedor. En nuestro caso, queremos proporcionar una lista de variables de entorno a través de un archivo. Por lo tanto, utilizaremos el método --env-file .
Con su editor preferido, cree un archivo llamado env en el directorio django_project:
|
1 |
nano env |
Pegue la siguiente lista de variables:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
DJANGO_SECRET_KEY=tu_clave_secreta DEBUG= DJANGO_LOGLEVEL=info DJANGO_ALLOWED_HOSTS=direccion_IP_de_tu_servidor DB_ENGINE=postgresql_psycopg2 DB_DATABASE=polls_db DB_USERNAME=hackins DB_PASSWORD=contraseña_de_tu_base_de_datos DB_HOST=host_de_tu_base_de_datos DB_PORT=puerto_de_tu_base_de_datos STATIC_DEFAULT_FILE_STORAGE=storages.backends.s3boto3.S3Boto3Storage STATIC_MINIO_BUCKET_NAME=test-bucket MINIO_ACCESS_KEY=tu_clave_de_acceso_minio MINIO_SECRET_KEY=tu_clave_secreta_minio MINIO_URL=tu_url_de_minio:tu_puerto_de_minio |
Las variables de la lista son las que definiste en los pasos anteriores:
-
DJANGO_SECRET_KEY: Genera un valor único e impredecible como se explica en la documentación de Django. Puedes usar este comando para generar una cadena aleatoria y asignarla a la variable:
|
1 |
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' |
-
DEBUG: Hemos establecido este valor en True, pero para un despliegue en producción, recuerda establecerlo en False dejándolo en blanco.
-
DJANGO_LOGLEVEL: hemos establecido esto en info, no dudes en ajustarlo al nivel que desees.
-
DJANGO_ALLOWED_HOSTS: establece este valor en la dirección IP del servidor Ubuntu que ejecuta tus contenedores Docker. Opcionalmente, establécelo en *, un comodín que coincide con todos los hosts si estás en modo de desarrollo.
-
DB_DATABASE: si utilizaste un nombre de base de datos diferente, establécelo aquí de manera adecuada.
-
DB_USERNAME: establece esto con el nombre de usuario que elegiste para tu base de datos.
-
DB_PASSWORD: establece esto con la contraseña que elegiste para tu base de datos.
-
DB_HOST: establece esto en el host que ejecuta tu instancia de base de datos tal como lo configuraste en el Paso uno.
-
DB_PORT: establece esto en el puerto de tu base de datos.
-
STATIC_MINIO_BUCKET_NAME: establece esto con el nombre del bucket que creaste en tu cuenta de MinIO Cloud Storage.
Guarda y cierra el archivo cuando termines de editar.
Las configuraciones de entorno ya están listas. Necesitamos ejecutar el contenedor pasando argumentos para anular el comando CMD predeterminado y crear el esquema de la base de datos utilizando los comandos manage.py makemigrations y manage.py migrate.
Aquí está el comando:
|
1 |
docker run --env-file env django-polls:v1 sh -c "python manage.py makemigrations && python manage.py migrate" |
En este comando, estamos ejecutando la imagen de contenedor django-polls:v1, utilizando la bandera –env-file para pasar el archivo de variables de entorno. También anulamos el comando CMD predeterminado con sh -c "python manage.py makemigrations && python manage.py migrate" Cuando se ejecuta este comando para iniciar el contenedor, creará el esquema de la base de datos tal como se define en el código de la aplicación.
Si tiene éxito, deberías ver una salida similar a la siguiente:

La salida indica que el esquema de la base de datos se ha creado correctamente.
El siguiente paso es crear un usuario administrador para la aplicación Django. Levantaremos el contenedor e iniciaremos una shell interactiva dentro con el siguiente comando:
|
1 |
docker run -i -t --env-file env django-polls:v1 sh |
El comando inicia el contenedor con un prompt de shell que puedes usar para interactuar con la shell de Python. Creemos un usuario:
|
1 |
python manage.py createsuperuser |
Sigue las instrucciones para proporcionar un nombre de usuario, dirección de correo electrónico, contraseña, vuelve a escribir la contraseña y presiona enter para crear el usuario. Sal de la shell y detén el contenedor presionando CTRL+D.
A continuación, necesitamos ejecutar el contenedor nuevamente, anulando el comando predeterminado con el comando de Django collectstatic para generar los archivos estáticos de la aplicación y subirlos a tu servicio de almacenamiento en la nube MinIO:
|
1 |
docker run --env-file env django-polls:v1 sh -c "python manage.py collectstatic --noinput" |
Cuando se complete, deberías ver una salida similar a la siguiente, que indica que tu contenedor se conectó correctamente al servicio de almacenamiento MinIO y subió los archivos estáticos:
![]()
Nuestro bucket de almacenamiento ahora se ve así, con los directorios que creó Django:

Finalmente, ahora podemos ejecutar la aplicación con el comando:
|
1 |
docker run --env-file env -p 80:8000 django-polls:v1 |
Aquí está la salida:

Cuando ejecutas el comando anterior, este ejecuta el comando CMD por defecto en tu imagen y expone el puerto 8000 tal como se definió. Ahora, Ubuntu en el puerto 80 se mapea al 8000 puerto del django-polls:v1 contenedor.
Ahora podemos probar la aplicación en el navegador. Ve a la dirección IP pública de tu servidor en el navegador: http://your_server_public_ip.
Es de esperar que encuentres un error 404 de página no encontrada, ya que según el Tutorial de Django, no definimos una ruta para / la ruta:

Tenemos la variable DEBUG establecida en True, por eso vemos esta página de error con mucha información crucial. Vamos a desconfigurar la variable DEBUG. Primero, deberás detener el contenedor en ejecución con CTRL+C. Luego, abre el archivo env :
|
1 |
nano env |
A continuación, busca la variable DEBUG y desconfigúrala, o déjala en blanco. La dejamos en blanco porque la función getenv interpreta False como una cadena, por lo que devuelve true:
|
1 |
DEBUG= |
Guarda el archivo y vuelve a ejecutar el contenedor con el comando:
|
1 |
docker run --env-file env -p 80:8000 django-polls:v1 |
Si visitas este http://your_server_public_ip en tu navegador, deberías ver la página 404 por defecto:

Has visto cómo puedes manipular el comportamiento en tiempo de ejecución de tu aplicación Django utilizando variables de entorno, sin modificar el código fuente.
Navega a http://your_server_public_ip/polls para ver la página de inicio de Polls:

No tenemos encuestas ya que acabamos de implementar la aplicación.
Navega a la interfaz de administración: http://your_server_public_ip/admin para ver la ventana de autenticación de administración:

Proporciona las credenciales que habías establecido con el comando createsuperuser para iniciar sesión. Ahora deberías estar en la interfaz de la página de administración:

Ten en cuenta que todos los archivos estáticos se sirven desde el servicio de almacenamiento externo que habíamos configurado. Puedes hacer clic derecho en la ventana de tu navegador y seleccionar Ver código fuente de la página:

Puedes agregar algunas preguntas y opciones y probar el rendimiento general de la aplicación:

Vuelve al índice de Polls http://your_server_public_ip/polls e intenta votar en la pregunta:

Después de haber probado y confirmado que todo funciona como se esperaba, puedes detener el contenedor.
Conclusión
Has configurado con éxito una aplicación web Django para que funcione bien en un entorno basado en contenedores. Esto implicó adaptar la aplicación para que funcione con variables de entorno externas, configurar la aplicación para usar un servicio de almacenamiento en la nube para los archivos estáticos y crear un Dockerfile para la imagen del contenedor. Puedes ver los cambios que hemos realizado para dockerizar la aplicación en la rama django-polls-docker del repositorio de GitHub de django-polls.
A partir de aquí, las posibilidades están limitadas únicamente por tu imaginación. Puedes configurar un proxy inverso Nginx para que se sitúe entre los clientes y el servidor Gunicorn. También puedes agregar Certbot para obtener certificados TLS para asegurar tu servidor Nginx. Recomendamos agregar un proxy HTTP para amortiguar a los clientes lentos y proteger tu servidor Gunicorn de ataques de denegación de servicio.
Aunque definimos 3 workers en el comando de inicio del Dockerfile, puedes establecer tu número preferido según los recursos disponibles en tu servidor. Puedes encontrar más información en los documentos de diseño oficiales de Gunicorn. Si lo deseas, puedes subir la imagen de Docker que creaste a Dockerhub e intentar implementarla en varios entornos que tengan Docker instalado. Si deseas obtener más información, sigue consultando nuestro blog de tutoriales ya que realizaremos un tutorial de seguimiento para asegurar la aplicación Django con Nginx y Let’s Encrypt.
Finalmente, aquí tienes más recursos que te ayudarán a utilizar Docker:
- Cómo alojar un repositorio de imágenes de Docker y compilar imágenes de Docker con una instancia autogestionada de GitLab en Ubuntu 20.04
- Trabajar con volúmenes de datos de Docker en Ubuntu 20.04
- Compilar e implementar una aplicación Flask con Docker en Ubuntu 20.04
- Cómo implementar WordPress con contenedores Docker en Ubuntu 20.04
¡Feliz computación!
Comentarios
Aún no hay comentarios. Sea el primero.