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.

También te podría gustar...