Introducción

En este post vamos a configurar contenedores de Docker para ejecutar aplicaciones web Python. Para ello, vamos a utilizar una aplicación web Python sencilla que se encuentra en el repositorio de GitHub.

Entorno de desarrollo

Vamos a crear un entorno de desarrollo en el que realizaremos las pruebas necesarias para la puesta a punto antes de lanzar nuestra aplicación en producción.

También vamos a crear dos contenedores que estarán conectados a la misma red. Una vez comprobado que la aplicación funciona, pasaremos a crear el docker-compose para pasarlo a producción.

Creación de la red

Para crear la red, ejecutamos el siguiente comando:

docker network create net_django

Creación del contenedor de la base de datos

Ya creada la red en la que van a ir conectados los contenedores, nos ponemos manos a la obra y creamos el contenedor de la base de datos. Para ello, ejecutamos el siguiente comando:

docker run -d --name mariadb -v vol_polls:/var/lib/mysql --network net_django -e MARIADB_ROOT_PASSWORD=admin -e MARIADB_USER=django -e MARIADB_PASSWORD=admin -e MARIADB_DATABASE=django mariadb

Tendremos que modificar el fichero settings.py de la aplicación web para que sea capaz de leer las variables de entorno:

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ.get("BASE_DATOS"),
        'USER': os.environ.get('USUARIO'),
        'PASSWORD': os.environ.get("CONTRA"),
        'HOST': os.environ.get('HOST'),
        'PORT': '3306',
    }
}
ALLOWED_HOSTS = [os.environ.get("ALLOWED_HOSTS")]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
CSRF_TRUSTED_ORIGINS = ['http://*.mariatec.es','http://*.127.0.0.1','https://*.mariatec.es','https://*.127.0.0.1']

La estructura del directorio de la aplicación web es la siguiente:

├── practica2
│   ├── django_tutorial
│   │   ├── manage.py
│   │   ├── requirements.txt
│   ├── docker-compose.yml
│   ├── Dockerfile
│   ├── polls.sh

Creamos el fichero Dockerfile a partir de la imagen de Python:

FROM python:3
WORKDIR /usr/src/app
MAINTAINER Maria Jesús Alloza Rodríguez 'mariajesus.allozarodriguez@gmail.com'
RUN apt-get install git && pip install --root-user-action=ignore --upgrade pip && pip install --root-user-action=ignore django mysqlclient
RUN git clone https://github.com/Legnakra/django_tutorial.git /usr/src/app && mkdir static
ADD ./polls.sh /usr/src/app/
RUN chmod +x /usr/src/app/polls.sh
ENV ALLOWED_HOSTS='*'
ENV HOST=mariadb
ENV USUARIO=django
ENV CONTRA=django
ENV BASE_DATOS=django
ENV DJANGO_SUPERUSER_PASSWORD=admin
ENV DJANGO_SUPERUSER_USERNAME=admin
ENV DJANGO_SUPERUSER_EMAIL=admin@example.org
ENTRYPOINT ["/usr/src/app/polls.sh"]

Una vez terminado de crear el fichero Dockerfile, creamos el fichero django_polls.sh:

#! /bin/sh

python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py createsuperuser --noinput
python3 manage.py collectstatic --noinput
python3 manage.py runserver 0.0.0.0:8006

Creamos la imagen de Docker:

docker build -t legnakra/django:v1 .

Ejecutando docker run -d --name polls --network django-net -p 8080:8006 legnakra/django:v1 podemos ver que la aplicación se ejecuta correctamente.

Tras ver como en la imagen anterior, todo funciona correctamente, nos disponemos a crear el docker-compose que levantará los dos contenedores que hemos creado.

vi docker-compose.yml
version: '3.7'
services:
  django-tutorial:
    container_name: django-tutorial
    image: legnakra/django:v1
    restart: always
    environment:
      ALLOWED_HOSTS: "*"
      HOST: bd_mariadb_django
      USUARIO: django
      CONTRA: django
      BASE_DATOS: django
      DJANGO_SUPERUSER_PASSWORD: admin
      DJANGO_SUPERUSER_USERNAME: admin
      DJANGO_SUPERUSER_EMAIL: admin@admin.org
    ports:
      - 8084:8006
    depends_on:
      - db_django
  db_django:
    container_name: bd_mariadb_django
    image: mariadb:latest
    restart: always
    environment:
      MARIADB_ROOT_PASSWORD: root
      MARIADB_DATABASE: django
      MARIADB_USER: django
      MARIADB_PASSWORD: django
    volumes:
      - mariadb_data_django:/var/lib/mysql
    networks:
      - net-mariatec
volumes:
    mariadb_data_django:
netwoks:
  net-mariatec:
    name: net-mariatec
    external: true

Levantamos el escenario de nuestro entorno de desarrollo con docker-compose up -d y podemos comprobar que todo funciona correctamente.

Nos dirigimos a la zona de administración con las credenciales que hemos configurado en el fichero docker-compose.yml y podemos ver que accedemos y podemos crear nuevas encuestas.

Entorno de producción

Ya tenemos la aplicación funcionando en nuestro entorno de desarrollo, por lo que ahora solo queda que nos vayamos al entorno de producción y despleguemos la aplicación.

Para ello, nos vamos a crear un registro en nuestro servidor DNS para que podamos acceder a la aplicación desde el exterior.

⬜️ django.mariatec.es CNAME mariatec.es

Generamos el certificado SSL para poder acceder a la aplicación desde el exterior.

certbot certonly --standalone -d django.mariatec.com

Tras generarlos, creamos el proxy de nginx para poder acceder a la aplicación desde el exterior.

vi /etc/nginx/sites-available/django.mariatec.es

recuerda que debe ser escuchado por elpuerto 8084.

server {
        listen 80;
        listen [::]:80;

        server_name django.mariatec.es;

        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        ssl    on;
        ssl_certificate /etc/letsencrypt/live/django.mariatec.es/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/django.mariatec.es/privkey.pem;

        index index.html index.php index.htm index.nginx-debian.html;

        server_name django.mariatec.es;

        location / {
                proxy_pass http://localhost:8084;
                include proxy_params;
        }
}

Creamos el enlace simbólico para que nginx pueda cargar la configuración y reniciamos el servicio de nginx.

ln -s /etc/nginx/sites-available/django /etc/nginx/sites-enabled/django

systemctl restart nginx

Si accedemos desde nuestro navegador a la dirección https://django.mariatec.es podemos ver que accedemos a la aplicación.

Y que podemos acceder a la zona de administración.