Implantación de aplicaciones web Python en docker
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.