Implantación de aplicaciones web Python en Docker

Í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.

comments powered by Disqus

Relacionados

Configuración de reglas de cortafuegos en router Linux usando iptables

Existen diferentes formas de implementar un cortafuegos en una red, ya sea por nodos o de forma perimetral. En ocasiones se puede dedicar un dispositivo exclusivamente para esta finalidad pero los routers también pueden cumplir esta función. En este post se muestra cómo configurar reglas de cortafuegos en routers Linux en este escenario basado en la saga “Los juegos del hambre”.

Leer

Ejemplos de uso de comandos básicos en Debian

En esta entrada se recogen algunos ejercicios básicos que demuestran el uso de los comandos más usados en Debian y otras distribuciones GNU/Linux.

Leer

Cómo crear una instancia basada en un volumen en OpenStack

OpenStack es un proyecto de cloud computing (computación en la nube) de software libre y código abierto. Ofrece una estructura como servicio (IaaS) y permite virtualizar equipos en los servidores en los que esté configurado. En este post se muestra, a través de un ejemplo práctico cómo se puede crear una instancia basada en un volumen en OpenStack y cómo se puede volcar el contenido de un sistema a un nuevo volumen con mayor capacidad de almacenamiento.

Leer