Dockerizar una aplicación Flask con Docker en Debian 10
Docker es una herramienta de código abierto diseñada para facilitar la creación, despliegue y ejecución de aplicaciones mediante el uso de contenedores. Un contenedor es un paquete de software que empaqueta el código y todas sus dependencias para que la aplicación se ejecute de forma rápida y fiable de un entorno informático a otro.
Flask es un popular framework web de Python. Se clasifica como microframework porque no requiere herramientas ni bibliotecas particulares. Comparado con otros frameworks, es ligero y muy estructurado.
En este tutorial, explicaremos cómo desplegar una aplicación Flask con Docker en un servidor Debian 10.
Requisitos previos
- Un servidor que ejecute Debian 10.
- Una contraseña de root configurada en tu servidor.
Cómo empezar
Antes de empezar, es una buena idea actualizar los paquetes de tu sistema a la última versión. Puedes actualizar todos los paquetes con el siguiente comando:
apt-get update -y apt-get upgrade -y
Una vez actualizados todos los paquetes, reinicia tu sistema para aplicar los cambios.
Instala las dependencias necesarias
A continuación, tendrás que instalar el servidor web Nginx y otras dependencias en tu sistema. Puedes instalarlas todas utilizando el siguiente comando:
apt-get install nginx apt-transport-https ca-certificates curl gnupg2 software-properties-common curl -y
Una vez instalados todos los paquetes, puedes pasar al siguiente paso.
Instalar Docker
Por defecto, la última versión de Docker no está disponible en el repositorio de Debian 10. Así que es una buena idea instalarla desde el repositorio oficial de Docker.
Primero, descarga y añade la clave GPG con el siguiente comando:
wget https://download.docker.com/linux/debian/gpg apt-key add gpg
A continuación, añade el repositorio de Docker con el siguiente comando:
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian buster stable"
A continuación, actualiza el repositorio e instala el Docker con el siguiente comando:
apt-get update -y apt-get install docker-ce -y
Una vez que la instalación se haya completado con éxito, verifica el estado del Docker con el siguiente comando:
systemctl status docker
Deberías obtener la siguiente salida:
? docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2020-04-19 06:26:25 UTC; 1min 8s ago Docs: https://docs.docker.com Main PID: 8883 (dockerd) Tasks: 10 Memory: 46.6M CGroup: /system.slice/docker.service ??8883 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.413828757Z" level=warning msg="Your kernel does not support swap memory limit Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.413876690Z" level=warning msg="Your kernel does not support cgroup rt period" Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.413889604Z" level=warning msg="Your kernel does not support cgroup rt runtime Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.414115814Z" level=info msg="Loading containers: start." Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.788332166Z" level=info msg="Default bridge (docker0) is assigned with an IP a Apr 19 06:26:24 debian10 dockerd[8883]: time="2020-04-19T06:26:24.972022325Z" level=info msg="Loading containers: done." Apr 19 06:26:25 debian10 dockerd[8883]: time="2020-04-19T06:26:25.010940205Z" level=info msg="Docker daemon" commit=afacb8b7f0 graphdriver(s)=o Apr 19 06:26:25 debian10 dockerd[8883]: time="2020-04-19T06:26:25.011145541Z" level=info msg="Daemon has completed initialization" Apr 19 06:26:25 debian10 systemd[1]: Started Docker Application Container Engine. Apr 19 06:26:25 debian10 dockerd[8883]: time="2020-04-19T06:26:25.074603639Z" level=info msg="API listen on /var/run/docker.sock"
En este punto, Docker está instalado y funcionando. Ahora puedes pasar al siguiente paso.
Configurar la estructura de directorios de Flask
A continuación, tendrás que crear una estructura de directorios para alojar tu aplicación Flask.
Vamos a crear un directorio llamado flask dentro del directorio /var/www/:
mkdir -p /var/www/flask
A continuación, cambia el directorio a flask y crea la estructura de directorios para flask:
cd /var/www/flask mkdir -p app/static mkdir -p app/templates
El directorio static se utiliza para almacenar imágenes, CSS y archivos JavaScript, mientras que el directorio templates se utiliza para almacenar las plantillas HTML de tu proyecto.
A continuación, tendrás que crear un archivo __init__.py dentro del directorio app:
nano app/__init__.py
Añade el siguiente contenido para crear una instancia de Flask e importar la lógica del archivo views.py:
from flask import Flask app = Flask(__name__) from app import views
Guarda y cierra el archivo y, a continuación, crea el archivo views.py en el directorio de tu app.
nano app/views.py
Añade las siguientes líneas
from app import app @app.route('/') def home(): return "hello world!"
Guarda y cierra el archivo y crea el archivo uwsgi.ini con el siguiente comando:
nano uwsgi.ini
Este archivo contendrá las configuraciones uWSGI para nuestra aplicación como se muestra a continuación:
[uwsgi] module = main callable = app master = true
Guarda y cierra el archivo cuando hayas terminado. uWSGI es una opción de despliegue para Nginx que es a la vez un protocolo y un servidor de aplicaciones.
A continuación, tendrás que crear el archivo main.py para importar la instancia de Flask llamada app del paquete de la aplicación. Puedes crearlo con el siguiente comando:
nano main.py
Añade la siguiente línea:
from app import app
Guarda y cierra el archivo cuando hayas terminado. A continuación, crea un archivo requirements.txt para especificar las dependencias que el gestor de paquetes pip instalará en tu despliegue Docker:
nano requirements.txt
Añade la siguiente línea que coincida con la última versión de Flask:
Flask==1.1.2
Guarda y cierra el archivo cuando hayas terminado.
Llegados a este punto, tu aplicación Flask se ha configurado correctamente. Ahora puedes pasar al siguiente paso.
Configurar Docker para desplegar Flask
A continuación, tendrás que crear un Dockerfile para construir y desplegar una aplicación Flask.
En primer lugar, crea un Dockerfile con el siguiente comando:
cd /var/www/flask nano Dockerfile
Añade las siguientes líneas:
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7 RUN apk --update add bash nano ENV STATIC_URL /static ENV STATIC_PATH /var/www/app/static COPY ./requirements.txt /var/www/requirements.txt RUN pip install -r /var/www/requirements.txt
Guarda y cierra el archivo cuando hayas terminado. A continuación, crea un script start.sh para construir una imagen a partir del Dockerfile y crear un contenedor a partir de la imagen Docker resultante.
nano start.sh
Añade la siguiente línea:
#!/bin/bash app="docker.test" docker build -t ${app} . docker run -d -p 56733:80 \ --name=${app} \ -v $PWD:/app ${app}
Guarda y cierra el archivo cuando hayas terminado.
Nota: Asegúrate de que el puerto 56733 está libre y utilizable.
Por último, ejecuta el script utilizando el siguiente comando:
bash start.sh
Esto creará la imagen Docker y construirá un contenedor a partir de la imagen resultante, como se muestra a continuación:
Sending build context to Docker daemon 9.728kB Step 1/6 : FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7 python3.6-alpine3.7: Pulling from tiangolo/uwsgi-nginx-flask 48ecbb6b270e: Pull complete 692f29ee68fa: Pull complete f75fc7ac1098: Pull complete c30e40bb471c: Pull complete Successfully built f5de17e1ce82 Successfully tagged docker.test:latest 22cd2bd23c9190cf2900fa1d7c55e4765a266e68c74dc1e6858872e9ebe7bdcd
Ahora puedes listar los contenedores en ejecución con el siguiente comando:
docker ps
Deberías obtener la siguiente salida:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 22cd2bd23c91 docker.test "/entrypoint.sh /sta…" About a minute ago Up About a minute 443/tcp, 0.0.0.0:56733->80/tcp docker.test
También puedes verificar el contenedor Docker visitando la URL http://your-server-ip:56733. Deberías ver la siguiente pantalla:
Desplegar archivos de plantilla
También puedes desplegar archivos de plantilla para servir contenido estático y dinámico. Puedes crear una plantilla de página de inicio para tu aplicación con el siguiente comando:
nano app/templates/home.html
Añade los siguientes códigos:
<!doctype html> <html lang="en-us"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>Welcome Flask</title> </head> <body> <h1>Home Page</h1> <p>This is the home page of our flask application.</p> </body> </html>
Guarda y cierra el archivo cuando hayas terminado. A continuación, tendrás que modificar el archivo views.py para servir el archivo recién creado:
nano app/views.py
Actualiza el archivo como se muestra a continuación:
from flask import render_template from app import app @app.route('/') def home(): return "hello world!" @app.route('/template') def template(): return render_template('home.html')
Guarda y cierra el archivo. A continuación, tendrás que reiniciar los contenedores Docker para aplicar los cambios.
Puedes reiniciar el contenedor Docker llamado docker.test con el siguiente comando:
docker stop docker.test docker start docker.test
Ahora, abre tu navegador web y escribe la URL http://your-server-ip:56733/template. Deberías ver tu plantilla recién creada en la siguiente pantalla:
Conclusión
Enhorabuena! has desplegado con éxito una aplicación Flask con Docker en un servidor Debian 10. Ahora puedes replicar la aplicación en distintos servidores con una reconfiguración mínima. No dudes en preguntarme si tienes alguna duda.