Implantación de aplicaciones web Python en Docker
- Francisco Javier Huete
- Implantacion
- February 24, 2025
Índice
Creación de una imagen docker a partir de una aplicación Python
Para implantar aplicaciones Python usando docker hay que crear una imagen Docker a partir de la aplicación para que se pueda implantar. En este caso se implanta una aplicación Python escrita con django llamada django_publicaciones. Esta aplicación debe almacenar su información en un contenedor Docker MariaDB con un volumen para almacenar los datos de manera persistente. Por tanto, la aplicación se tiene que configurar para indicar los parámetros de conexión a la base de datos: usuario, contraseña, host y base de datos. La aplicación, además, necesita un usuario administrador para el acceso.
El punto de partida para crear esta imagen Docker es el siguiente árbol de directorios:
django
├── build
│ ├── Dockerfile
│ ├── app
│ │ ├── ...
│ │ ├── django_publicaciones
│ │ └── publicaciones
│ └── docker-entrypoint.sh
└── docker-compose.yml
Para configurar la conexión a la base de datos de la aplicación se edita el fichero app/django_publicaciones/settings.py. Esta configuración debe tener en cuenta el uso de variables de entorno para la creación de los contenedores.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ.get("DB"),
'USER': os.environ.get("DB_USER"),
'PASSWORD': os.environ.get("DB_PASS"),
'HOST': os.environ.get("DB_HOST"),
'PORT': '',
}
}
...
CSRF_TRUSTED_ORIGINS = [os.environ.get("URL_BASE")]
Para que la aplicación pueda acceder a las variables de entorno hay que importar la librería os
de python en este fichero.
import os
Cuando el contenedor Docker se ejecute debe realizar una serie de acciones: crear las tablas en la base de datos con el comando migrate
, crear el super usuario con el comando createsurperuser
y ejecutar la aplicacion con el comando runserver
. Estas acciones se pueden indicar en un script que se ejecute al arrancar el contenedor.
#!/bin/bash
export DJANGO_SUPERUSER_PASSWORD=$DJANGO_PASS
cd /usr/src/app
curl https://raw.githubusercontent.com/vishnubob/wait-for-it/refs/heads/master/wait-for-it.sh > wait-for-it.sh
chmod +x wait-for-it.sh
./wait-for-it.sh db:3306 --timeout=30 --strict
python3 manage.py migrate
python3 manage.py createsuperuser --username $DJANGO_USER --email $DJANGO_MAIL --noinput
python3 manage.py runserver 0.0.0.0:3000
En el Dockerfile se deben indicar, junto a este script, las variables de entorno necesarias para crear tanto el contenedor de la aplicación como la base de datos, así como los comandos que se deben ejecutar para la construcción de la imagen.
FROM python:3.12.1-bookworm
WORKDIR /usr/src/app
COPY app .
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh \
&& pip install mysqlclient \
&& pip install --no-cache-dir --break-system-packages -r requirements.txt
EXPOSE 3000
ENV URL_BASE=http://localhost
ENV DB_HOST=localhost
ENV DB_USER=usuario
ENV DB_PASS=asdasd
ENV DB=django
ENV DJANGO_MAIL=mail@mail.org
ENV DJANGO_USER=admin
ENV DJANGO_PASS=admin
CMD /usr/local/bin/docker-entrypoint.sh
A partir de este fichero, se puede crear la imagen docker de la aplicación.
docker build -t fjhuete/django:v1 .
En este punto, es importante recordar que, cuando se ejecutan contenedores en instancias de OpenStack puede surgir un problema debido a que el MTU de las redes de OpenStack es más pequeño que el MTU por defecto. Este problema se puede solucionar siguiendo los pasos de este tutorial
Para evitar los problemas generados por la diferencia del MTU en la red de OpenStack se crea el fichero /etc/docker/daemon.json con el siguiente contenido:
{
"mtu": 1442
}
Y después se reinicia el demonio de docker.
sudo systemctl daemon-reload
sudo systemctl restart docker
Además de la imagen creada, para que la aplicación funcione necesita conectarse a una base de datos. Esta conexión se puede configurar en un fichero docker-compose que despliegue todos los contenedores necesarios para el funcionamiento de la aplicación.
services:
app:
container_name: publicaciones
image: fjhuete/django:${VERSION_DJANGO}
restart: always
environment:
URL_BASE: ${URL_BASE}
DB_HOST: ${DB_HOST}
DB_USER: ${DB_USER}
DB_PASS: ${DB_PASS}
DB: ${DB}
DJANGO_MAIL: ${DJANGO_MAIL}
DJANGO_USER: ${DJANGO_USER}
DJANGO_PASS: ${DJANGO_PASS}
ports:
- ${PUERTO}:3000
depends_on:
- db
db:
container_name: django_db
image: mariadb:${VERSION_MARIADB}
restart: always
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- django_data:/var/lib/mysql
volumes:
django_data:
Por defecto, durante la creación de los contenedores se pasarán las variables de entorno indicadas en el Dockerfile. Para modificar estas variables en la creación de los contenedores se puede usar un fichero .env con los valores correctos.
VERSION_DJANGO=v1
VERSION_MARIADB=latest
URL_BASE=https://djangodocker.javihuete.site
DB_HOST=django_db
DB_USER=usuario
DB_PASS=asdasd
DB=django
DJANGO_MAIL=mail@mail.org
DJANGO_USER=admin
DJANGO_PASS=admin
MYSQL_DATABASE=django
MYSQL_USER=usuario
MYSQL_PASSWORD=asdasd
MYSQL_ROOT_PASSWORD=asdasd
Estas variables serán las que se usen al desplegar la aplicación con el comando docker compose up -d
.