El autor seleccionó el Tech Education Fund para que recibiese una donación como parte del programa Write for DOnations.

Introducción

Docker es una aplicación de código abierto que permite a los administradores crear, administrar, implementar y replicar aplicaciones usando contenedores. Los contenedores pueden considerarse como un paquete que alberga las dependencias que una aplicación requiere para ejecutarse a nivel de sistema operativo. Esto significa que cada aplicación implementada usando Docker reside en un entorno propio y sus requisitos se gestionan por separado.

Flask es un micromarco web que se compila con Python. Se denomina micromarco porque no requiere herramientas ni complementos específicos para ejecutarse. El marco de Flask es ligero y flexible, pero muy estructurado. Esto lo convierte en la opción preferida por encima de otros marcos.

Implementar una aplicación de Flask con Docker le permitirá replicarla en varios servidores con una reconfiguración mínima.

A través de este tutorial, creará una aplicación de Flask y la implementará con Docker. En este artículo, también se abordará la manera de actualizar una aplicación tras la implementación.

Requisitos previos

Para completar este tutorial, necesitará lo siguiente:

Paso 1: Configurar la aplicación de Flask

Para comenzar, creará una estructura de directorios que contendrá su aplicación de Flask. En este tutorial, se creará un directorio llamado TestApp en /var/www, pero puede modificar el comando para darle el nombre que desee.

  • sudo mkdir /var/www/TestApp

Diríjase al directorio TestApp recién creado:

  • cd /var/www/TestApp

A continuación, cree la estructura de carpetas para la aplicación de Flask:

  • sudo mkdir -p app/static app/templates

El indicador -p marca que mkdir creará un directorio y todos los directorios principales que no existen. En este caso, mkdir creará el directorio principal app en el proceso de creación de los directorios static y templates.

El directorio app contendrá todos los archivos relacionados con la aplicación de Flask, como sus vistas y modelos. Las vistas son el código que uste escribe para responder a las solicitudes a su aplicación. Los modelos crean componentes de aplicaciones, y admiten patrones comunes dentro de una aplicación y entre varias de estas.

El directorio static es el punto en el que se alojan recursos como los archivos de imagen, CSS y JavaScript. El directorio templates es el espacio en el que dispondrá las plantillas HTML para su proyecto.

Ahora que la estructura básica de carpetas está completa, cree los archivos necesarios para ejecutar la aplicación de Flask. Primero, cree un archivo __init__.py dentro del directorio app. Este archivo indica al intérprete de Python que el directorio app es un paquete y debería tratarse como tal.

Ejecute el siguiente comando para crear el archivo:

  • sudo nano app/__init__.py

Los paquetes de Python le permiten agrupar módulos en jerarquías o espacios de nombres lógicos. Este enfoque permite desglosar el código en bloques individuales y manejables que realizan funciones específicas.

A continuación, añadirá código al __init__.py que creará una instancia de Flask e importará la lógica desde el archivo views.py, que creará tras guardar este archivo. Añada el siguiente código a su nuevo archivo:

/var/www/TestApp/__init__.py
from flask import Flask
app = Flask(__name__)
from app import views

Una vez que lo haga, guarde y cierre el archivo.

Después de crear el archivo __init__.py, estará listo para crear el archivo views.py en su directorio app. Este archivo contendrá la mayor parte de la lógica de su aplicación.

  • sudo nano app/views.py

A continuación, añada el código a su archivo views.py. Con este código se mostrará la cadena hello world! a los usuarios que visiten su página web:

/var/www/TestApp/app/views.py
from app import app

@app.route('/')
def home():
   return "hello world!"

La línea @app.route sobre la función se conoce como decorador. Los decoradores modifican la función que los sigue. En este caso, el decorador indica a Flask la URL que desencadenará la función home(). El texto hello world mostrado por la función home se mostrará al usuario en el navegador.

Una vez que esté preparado el archivo views.py, estará listo para crear el archivo uwsgi.ini. Este archivo contendrá las configuraciones de uWSGI para nuestra aplicación. uWSGI es una opción de implementación para Nginx que es tanto un protocolo como un servidor de aplicaciones; el servidor de aplicaciones puede proporcionar los protocolos uWSGI, FastCGI y HTTP.

Para crear este archivo, ejecute el siguiente comando:

  • sudo nano uwsgi.ini

A continuación, añada el siguiente contenido a su archivo para configurar el servidor uWSGI:

/var/www/TestApp/uwsgi.ini
[uwsgi]
module = main
callable = app
master = true

Este código define el módulo desde el que se proporcionará la aplicación de Flask. En este caso, este es el archivo main.py, citado aquí como main. La opción callable indica a uWSGI que use la instancia de app exportada por la aplicación principal. La opción master permite que su aplicación siga ejecutándose, de modo que haya poco tiempo de inactividad incluso cuando se vuelva a cargar toda la aplicación.

A continuación, cree el archivo main.py, que es el punto de entrada a la aplicación. El punto de entrada indica a uWSGI cómo interactuar con la aplicación.

  • sudo nano main.py

A continuación, copie lo siguiente y péguelo en el archivo. Con esto, se importará la instancia de Flask llamada app desde el paquete de la aplicación que se creó previamente.

/var/www/TestApp/main.py
from app import app

Finalmente, cree un archivo requirements.txt para especificar las dependencias que el administrador de paquetes pip instalará en su implementación de Docker:

  • sudo nano requirements.txt

Añada la siguiente línea para agregar Flask como dependencia:

/var/www/TestApp/app/requirements.txt
Flask==1.0.2

Esto especifica la versión de Flask que se instalará. En el momento en que se redactó este tutorial, la versión 1.0.2 fue la más reciente de Flask. Puede verificar si existen actualizaciones en el sitio web oficial de Flask.

Guarde y cierre el archivo. De esta manera, habrá configurado correctamente su aplicación de Flask y estará listo para configurar Docker.

Paso 2: Configurar Docker

A lo largo de este paso creará dos archivos, Dockerfile y start.sh, para crear su implementación de Docker. El archivo Dockerfile es un documento de texto que contiene los comandos utilizados para ensamblar la imagen. El archivo start.sh es una secuencia de comandos shell que creará una imagen y un contenedor desde Dockerfile.

Primero, cree Dockerfile.

  • sudo nano Dockerfile

A continuación, añada su configuración deseada a Dockerfile. Estos comandos especifican la forma en que se creará la imagen y los requisitos adicionales que se incluirán.

/var/www/TestApp/Dockerfile
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

En este ejemplo, la imagen de Docker se creará a partir de una imagen existente, tiangolo/uwsgi-nginx-flask, que podrá encontrar en DockerHub. Esta imagen de Docker concreta es una buena opción en comparación con otras, porque es compatible con una amplia variedad de versiones de Python e imágenes de SO.

Las primeras dos líneas especifican la imagen principal que utilizará para ejecutar la aplicación e instalar el procesador de comandos bash y el editor de texto nano. También instala el cliente git para realizar extracciones desde servicios de alojamiento de control de versiones, como GitHub, GitLab y Bitbucket, e incorporaciones en ellos. ENV STATIC_URL /static es una variable de entorno específica para esta imagen de Docker. Define la carpeta estática desde la cual se proporcionan todos los recursos como imágenes, archivos CSS y archivos JavaScript.

Las últimas dos líneas copiarán el archivo requirements.txt al contenedor para que pueda ejecutarse y luego analice el archivo requirements.txt para instalar las dependencias especificadas.

Guarde y cierre el archivo después de añadir su configuración.

Una vez que este listo su Dockerfile, casi estará preparado listo para escribir la secuencia de comandos start.sh que creará el contenedor de Docker. Antes de escribir la secuencia de comandos start.sh, primero asegúrese de disponer de un puerto abierto para usarlo en la configuración. Para verificar si hay un puerto libre, ejecute el siguiente comando:

  • sudo nc localhost 56733 < /dev/null; echo $?

Si el resultado del comando anterior es 1, el puerto estará libre y podrá utilizarse. De lo contrario, deberá seleccionar un puerto diferente para usarlo en su archivo de configuración start.sh.

Una vez que encuentre un puerto abierto para usarlo, cree la secuencia de comandos start.sh:

  • sudo nano start.sh

La secuencia de comandos start.sh es una secuencia de comandos de shell que creará una imagen desde Dockerfile y un contenedor a partir de la imagen de Docker resultante. Añada su configuración al nuevo archivo:

/var/www/TestApp/start.sh
#!/bin/bash
app="docker.test"
docker build -t ${app} .
docker run -d -p 56733:80 \
  --name=${app} \
  -v $PWD:/app ${app}

La primera línea se denomina shebang. Especifica que este es un archivo bash y se ejecutará como comandos. En la siguiente línea se especifica el nombre que desea dar a la imagen y al contenedor, y se guarda como una app con nombre variable. La siguiente línea indica a Docker que cree una imagen desde su Dockerfile ubicado en el directorio actual. Con esto, se creará una imagen llamada docker.test en este ejemplo.

Con las últimas tres líneas se crea un nuevo contenedor llamado docker.test que se expone en el puerto 56733. Finalmente, vincula el directorio actual al directorio /var/www del contenedor.

El indicador -d se utiliza para iniciar un contenedor en el modo de demonio, o como proceso en segundo plano. El indicador -p se incluye para vincular un puerto del servidor a un puerto concreto del contenedor Docker. En este caso, vinculará el puerto 56733 al puerto 80 en el contenedor Docker. El indicador -v especifica un volumen de Docker para montarlo en el contenedor y, en este caso, usted montará todo el directorio del proyecto en la carpeta /var/www del contenedor de Docker.

Ejecute la secuencia de comandos start.sh para crear la imagen de Docker y un contenedor a partir de la imagen resultante:

  • sudo bash start.sh

Una vez que la secuencia de comandos termine de ejecutarse, utilice el siguiente comando para enumerar todos los contenedores en ejecución:

  • sudo docker ps

Verá un resultado en el que se mostrarán los contenedores:

Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 58b05508f4dd docker.test "/entrypoint.sh /sta…" 12 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:56733->80/tcp docker.test

Verá el contenedor docker.test en ejecución. Ahora que se está ejecutando, visite la dirección IP en el puerto especificado de su navegador: http://ip-address56733.

Verá una página similar a la siguiente:

Página de inicio

Una vez completado este paso, habrá implementado correctamente su aplicación de Flask en Docker. A continuación, usará plantillas para mostrar el contenido a los usuarios.

Paso 3: Presentar archivos de plantillas

Las plantillas son archivos que muestran contenido estático y dinámico a los usuarios que visitan su aplicación. En este paso, creará una plantilla HTML con el propósito de producir una página de inicio para la aplicación.

Comience creando un archivo home.html en el directorio app/templates:

  • sudo nano app/templates/home.html

Añada el código para su plantilla. Con este código, se creará una página HTML5 que contiene un título y texto.

/var/www/TestApp/app/templates/home.html

<!doctype html>

<html lang="en-us">   
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>Welcome home</title>
  </head>

  <body>
    <h1>Home Page</h1>
    <p>This is the home page of our application.</p>
  </body>
</html>

Guarde y cierre el archivo una vez que agregue su plantilla.

A continuación, modifique el archivo app/views.py para presentar el archivo recién creado:

  • sudo nano app/views.py

Primero, añada la siguiente línea al inicio de su archivo para importar el método render_template desde Flask. Con este método se analiza un archivo HTML para presentar una página web al usuario.

/var/www/TestApp/app/views.py
from flask import render_template
...

Al final del archivo, también agregará una nueva ruta para representar el archivo de plantilla. Con este código se especifica que los usuarios reciben el contenido del archivo home.html cuando visitan la ruta /template en su aplicación.

/var/www/TestApp/app/views.py
...

@app.route('/template')
def template():
    return render_template('home.html')

El archivo app/views.py actualizado tendrá este aspecto:

/var/www/TestApp/app/views.py
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')

Guarde y cierre el archivo cuando termine.

Para que estos cambios se apliquen, deberá detener y reiniciar los contenedores de Docker. Ejecute el siguiente comando para volver a compilar el contenedor:

  • sudo docker stop docker.test && sudo docker start docker.test

Visite su aplicación en http://your-ip-address:56733/template para ver la nueva plantilla que se presenta.

Página de inicio

Con esto, habrá creado un archivo de plantilla de Docker que se presentará a los visitantes de su aplicación. En el siguiente paso, verá cómo los cambios que realice a su aplicación pueden aplicarse sin necesidad de reiniciar el contenedor de Docker.

Paso 4: Actualizar la aplicación

A veces, deberá realizar en la aplicación cambios que pueden incluir instalar nuevos requisitos, actualizar el contenedor de Docker o aplicar modificaciones vinculadas al HTML y a la lógica. A lo largo de esta sección, configurará touch-reload para realizar estos cambios sin necesidad de reiniciar el contenedor de Docker.

autoreloading de Python controla el sistema completo de archivos en busca de cambios y actualiza la aplicación cuando detecta uno. No se aconseja el uso de autoreloading en producción porque puede llegar a utilizar muchos recursos de forma muy rápida. En este paso, utilizará touch-reload para realizar la verificación en busca de cambios en un archivo concreto y volver a cargarlo cuando se actualice o sustituya.

Para implementar esto, abra su archivo uwsgi.ini:

  • sudo nano uwsgi.ini

A continuación, añada la línea resaltada al final del archivo:

/var/www/TestApp/uwsgi.ini
module = main
callable = app
master = true
touch-reload = /app/uwsgi.ini

Esto especifica un archivo que se modificará para activar una recarga completa de la aplicación. Una vez que realice los cambios, guarde y cierre el archivo.

Para demostrar esto, realice un pequeño cambio a su aplicación. Comience abriendo su archivo app/views.py:

  • sudo nano app/views.py

Sustituya la secuencia de comandos mostrada por la función home:

/var/www/TestApp/app/views.py
from flask import render_template
from app import app

@app.route('/')
def home():
    return "<b>There has been a change</b>"

@app.route('/template')
def template():
    return render_template('home.html')

Guarde y cierre el archivo después de realizar un cambio.

A continuación, si abre la página de inicio de su aplicación en http://ip-address56733<^> observará que los cambios no se reflejan. Esto se debe a que la condición para volver a cargar es un cambio en el archivo uwsgi.ini. Para volver a cargar la aplicación, use touch a fin de activar la condición:

  • sudo touch uwsgi.ini

Vuelva a cargar la página de inicio de la aplicación en su navegador. Verá que en la aplicación se incorporaron los cambios:

Página de inicio actualizada

Al completar este paso, habrá configurado una condición touch-reload para actualizar su aplicación tras realizar cambios.

Conclusión

A través de este tutorial, creó una aplicación de Flask y la implementó en un contenedor de Docker. También configuró touch-reload para actualizar su aplicación sin necesidad de reiniciar el contenedor.

Con su nueva aplicación en Docker, ahora podrá realizar el escalamiento de forma sencilla. Para obtener más información sobre el uso de Docker, consulte su documentación oficial.

0 Comments

Creative Commons License