Comment construire et déployer une application Flask à l’aide de Docker sur Ubuntu 18.04

_L’auteur a sélectionné le Tech Education Fund pour recevoir un don dans le cadre du programme Write for DOnations. _

introduction

Docker est une application open source qui permet aux administrateurs de créer, gérer, déployer et répliquer des applications à l’aide de conteneurs. Les conteneurs peuvent être considérés comme un package contenant les dépendances nécessaires à une application pour s’exécuter au niveau du système d’exploitation. Cela signifie que chaque application déployée à l’aide de Docker réside dans son propre environnement et que ses exigences sont gérées séparément.

Flask est un micro-framework Web construit sur Python. Il s’appelle micro-framework car il n’exige pas d’outils ni de plug-ins spécifiques. Le framework Flask est léger et flexible, tout en étant très structuré, ce qui le rend préférable aux autres frameworks.

Le déploiement d’une application Flask avec Docker vous permettra de répliquer l’application sur différents serveurs avec une reconfiguration minimale.

Dans ce didacticiel, vous allez créer une application Flask et la déployer avec Docker. Ce didacticiel couvrira également la mise à jour d’une application après le déploiement.

Conditions préalables

Pour suivre ce tutoriel, vous aurez besoin des éléments suivants:

Étape 1 - Configuration de l’application Flask

Pour commencer, vous allez créer une structure de répertoire qui contiendra votre application Flask. Ce tutoriel va créer un répertoire appelé + TestApp + dans + / var / www +, mais vous pouvez modifier la commande pour la nommer comme vous le souhaitez.

sudo mkdir /var/www/

Déplacez-vous dans le répertoire + TestApp + nouvellement créé:

cd /var/www/

Ensuite, créez la structure de dossiers de base pour l’application Flask:

sudo mkdir -p app/static app/templates

L’indicateur + -p + indique que + mkdir + créera un répertoire et tous les répertoires parents qui n’existent pas. Dans ce cas, + mkdir + créera le répertoire parent + app + dans le processus de création des répertoires + static + et + templates +.

Le répertoire + app + contiendra tous les fichiers liés à l’application Flask, tels que views et blueprints. Views est le code que vous écrivez pour répondre aux demandes de votre application. Blueprints créer des composants d’application et prendre en charge des modèles courants au sein d’une application ou de plusieurs applications.

Le répertoire + static + est l’endroit où résident les actifs tels que les images, CSS et JavaScript. Le répertoire + templates + est l’endroit où vous allez placer les templates HTML pour votre projet.

Maintenant que la structure de dossiers de base est terminée, créez les fichiers nécessaires à l’exécution de l’application Flask. Commencez par créer un fichier + init . Py dans le répertoire` + app`. Ce fichier indique à l’interpréteur Python que le répertoire + app + est un paquet et qu’il doit être traité comme tel.

Exécutez la commande suivante pour créer le fichier:

sudo nano app/__init__.py

Les packages en Python vous permettent de regrouper des modules dans des espaces de noms logiques ou des hiérarchies. Cette approche permet de diviser le code en blocs individuels gérables qui remplissent des fonctions spécifiques.

Ensuite, vous ajouterez du code au + init . Py + qui créera une instance Flask et importera la logique à partir du fichier + views.py +, que vous créerez après avoir enregistré ce fichier. Ajoutez le code suivant à votre nouveau fichier:

/var/www/TestApp/init.py

from flask import Flask
app = Flask(__name__)
from app import views

Une fois que vous avez ajouté ce code, enregistrez et fermez le fichier.

Avec le fichier + init . Py + créé, vous êtes prêt à créer le fichier + views.py + dans votre répertoire + app +. Ce fichier contiendra l’essentiel de la logique de votre application.

sudo nano app/views.py

Ensuite, ajoutez le code à votre fichier + views.py +. Ce code renverra la chaîne + hello world! + Aux utilisateurs qui visitent votre page Web:

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

from app import app

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

La ligne + @ app.route + au-dessus de la fonction est appelée decorator. Les décorateurs modifient la fonction qui la suit. Dans ce cas, le décorateur indique à Flask quelle URL déclenchera la fonction + home () +. Le texte + hello world + renvoyé par la fonction + home + sera affiché à l’utilisateur dans le navigateur.

Avec le fichier + views.py + en place, vous êtes prêt à créer le fichier + uwsgi.ini +. Ce fichier contiendra les configurations https://uwsgi-docs.readthedocs.io [uWSGI] pour notre application. uWSGI est une option de déploiement pour Nginx qui est à la fois un protocole et un serveur d’applications. le serveur d’applications peut servir les protocoles uWSGI, FastCGI et HTTP.

Pour créer ce fichier, exécutez la commande suivante:

sudo nano uwsgi.ini

Ensuite, ajoutez le contenu suivant à votre fichier pour configurer le serveur uWSGI:

/var/www/TestApp/uwsgi.ini

[uwsgi]
module = main
callable = app
master = true

Ce code définit le module à partir duquel l’application Flask sera servie. Dans ce cas, il s’agit du fichier + main.py +, référencé ici par + main +. L’option + callable + indique à uWSGI d’utiliser l’instance + app + exportée par l’application principale. L’option + master + permet à votre application de continuer à fonctionner, ce qui réduit les temps d’immobilisation, même lors du rechargement complet de l’application.

Ensuite, créez le fichier + main.py +, qui est le point d’entrée dans l’application. Le point d’entrée indique à uWSGI comment interagir avec l’application.

sudo nano main.py

Ensuite, copiez et collez le texte suivant dans le fichier. Cela importe l’instance Flask nommée + app + à partir du package d’application créé précédemment.

/var/www/TestApp/main.py

from app import app

Enfin, créez un fichier + Requirements.txt + pour spécifier les dépendances que le gestionnaire de packages + pip + installera sur votre déploiement Docker:

sudo nano requirements.txt

Ajoutez la ligne suivante pour ajouter Flask en tant que dépendance:

/var/www/TestApp/app/requirements.txt

Flask==1.0.2

Ceci spécifie la version de Flask à installer. Au moment de la rédaction de ce tutoriel, + 1.0.2 + est la dernière version de Flask. Vous pouvez vérifier les mises à jour sur le site officiel de Flask.

Enregistrez et fermez le fichier. Vous avez correctement configuré votre application Flask et êtes prêt à configurer Docker.

Étape 2 - Configuration de Docker

Dans cette étape, vous allez créer deux fichiers, + Dockerfile + et + start.sh +, pour créer votre déploiement Docker. Le + Dockerfile + est un document texte contenant les commandes permettant d’assembler l’image. Le fichier + start.sh + est un script shell qui va construire une image et créer un conteneur à partir du + Dockerfile +.

Commencez par créer le + Dockerfile.

sudo nano Dockerfile

Ensuite, ajoutez votre configuration désirée au + Dockerfile +. Ces commandes spécifient comment l’image sera construite et quelles exigences supplémentaires seront incluses.

/ var / www / TestApp / Dockerfile

FROM tiangolo/uwsgi-nginx-flask:
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

Dans cet exemple, l’image Docker sera construite à partir d’une image existante, + tiangolo / uwsgi-nginx-flask +, que vous trouverez sur https://hub.docker.com/r/tiangolo/uwsgi-nginx-flask [DockerHub]. Cette image Docker particulière est un bon choix par rapport aux autres car elle prend en charge une large gamme de versions Python et d’images de système d’exploitation.

Les deux premières lignes spécifient l’image parente que vous utiliserez pour exécuter l’application et installer le processeur de commande bash et l’éditeur de texte + nano +. Il installe également le client + git + pour extraire et pousser des services d’hébergement de contrôle de version tels que GitHub, GitLab et Bitbucket. + ENV STATIC_URL / static + est une variable d’environnement spécifique à cette image Docker. Il définit le dossier statique à partir duquel tous les actifs, tels que les images, les fichiers CSS et les fichiers JavaScript, sont servis.

Les deux dernières lignes copient le fichier + Requirements.txt dans le conteneur afin qu’il puisse être exécuté, puis analysent le fichier` + Requirements.txt` pour installer les dépendances spécifiées.

Enregistrez et fermez le fichier après avoir ajouté votre configuration.

Avec votre + Dockerfile + en place, vous êtes presque prêt à écrire votre script + start.sh + qui construira le conteneur Docker. Avant d’écrire le script + start.sh +, assurez-vous d’abord que vous avez un port libre à utiliser dans la configuration. Pour vérifier si un port est libre, exécutez la commande suivante:

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

Si le résultat de la commande ci-dessus est + 1 +, le port est libre et utilisable. Sinon, vous devrez sélectionner un autre port à utiliser dans votre fichier de configuration + start.sh +.

Une fois que vous avez trouvé un port ouvert à utiliser, créez le script + start.sh +:

sudo nano start.sh

Le script + start.sh + est un script de shell qui construit une image à partir du fichier + Dockerfile + et crée un conteneur à partir de l’image Docker obtenue. Ajoutez votre configuration au nouveau fichier:

/var/www/TestApp/start.sh

#!/bin/bash
app=""
docker build -t ${app} .
docker run -d -p :80 \
 --name=${app} \
 -v $PWD:/app ${app}

La première ligne s’appelle un shebang. Il spécifie qu’il s’agit d’un fichier bash et qu’il sera exécuté en tant que commande. La ligne suivante spécifie le nom que vous voulez donner à l’image et au conteneur et enregistre sous une variable nommée + app +. La ligne suivante indique à Docker de créer une image à partir de votre fichier + Dockerfile + situé dans le répertoire en cours. Cela créera une image appelée + docker.test + dans cet exemple.

Les trois dernières lignes créent un nouveau conteneur nommé + docker.test + exposé au port + 56733 +. Enfin, il relie le répertoire présent au répertoire + / var / www + du conteneur.

Vous utilisez l’indicateur + -d + pour démarrer un conteneur en mode démon ou en tant que processus en arrière-plan. Vous incluez l’indicateur + -p + pour lier un port du serveur à un port particulier du conteneur Docker. Dans ce cas, vous liez le port + 56733 + au port + 80 + du conteneur Docker. L’indicateur + -v + spécifie le volume Docker à monter sur le conteneur et, dans ce cas, vous montez le répertoire de projet entier dans le dossier + / var / www + du conteneur Docker.

Exécutez le script + start.sh + pour créer l’image Docker et créer un conteneur à partir de l’image résultante:

sudo bash start.sh

Une fois l’exécution du script terminée, utilisez la commande suivante pour répertorier tous les conteneurs en cours d’exécution:

sudo docker ps

Vous recevrez une sortie qui montre les conteneurs:

OutputCONTAINER 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

Vous constaterez que le conteneur + docker.test est en cours d’exécution. Maintenant qu’il est en cours d’exécution, visitez l’adresse IP du port indiqué dans votre navigateur: + http: //: +

Vous verrez une page semblable à la suivante:

image: https: //assets.digitalocean.com/articles/CART-62081/HelloWorld.png [la page d’accueil]

Dans cette étape, vous avez correctement déployé votre application Flask sur Docker. Ensuite, vous utiliserez des modèles pour afficher du contenu aux utilisateurs.

Étape 3 - Servir des fichiers de modèle

Templates sont des fichiers qui affichent un contenu statique et dynamique pour les utilisateurs qui visitent votre application. Dans cette étape, vous allez créer un modèle HTML pour créer une page d’accueil pour l’application.

Commencez par créer un fichier + home.html dans le répertoire` + app / templates`:

sudo nano app/templates/home.html

Ajoutez le code pour votre modèle. Ce code créera une page HTML5 contenant un titre et du texte.

/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>

Enregistrez et fermez le fichier une fois que vous avez ajouté votre modèle.

Ensuite, modifiez le fichier + app / views.py + pour servir le fichier nouvellement créé:

sudo nano app/views.py

Tout d’abord, ajoutez la ligne suivante au début de votre fichier pour importer la méthode + render_template + de Flask. Cette méthode analyse un fichier HTML pour rendre une page Web à l’utilisateur.

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

from flask import render_template
...

À la fin du fichier, vous ajouterez également une nouvelle route pour rendre le fichier de modèle. Ce code spécifie que le contenu du fichier + home.html + est servi aux utilisateurs chaque fois qu’ils visitent la route + / template + sur votre application.

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

...

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

Le fichier + app / views.py + mis à jour ressemblera à ceci:

/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')

Enregistrez et fermez le fichier lorsque vous avez terminé.

Pour que ces modifications prennent effet, vous devez arrêter et redémarrer les conteneurs Docker. Exécutez la commande suivante pour reconstruire le conteneur:

sudo docker stop  && sudo docker start

Rendez-vous à votre application sur + http: //: 56733 / template + pour voir le nouveau modèle servi.

image: https: //assets.digitalocean.com/articles/CART-62081/HomePage.png [page d’accueil]

Vous avez ainsi créé un fichier de modèle Docker destiné aux visiteurs de votre application. Dans l’étape suivante, vous verrez comment les modifications apportées à votre application peuvent prendre effet sans avoir à redémarrer le conteneur Docker.

Étape 4 - Mise à jour de l’application

Parfois, vous devrez modifier l’application, qu’il s’agisse de l’installation de nouvelles exigences, de la mise à jour du conteneur Docker ou des modifications HTML et logiques. Dans cette section, vous allez configurer + touch-reload + pour effectuer ces modifications sans qu’il soit nécessaire de redémarrer le conteneur Docker.

Python autoreloading surveille l’ensemble du système de fichiers pour rechercher les modifications et actualise l’application lorsqu’elle détecte une modification. Le chargement automatique est déconseillé en production car il peut devenir très gourmand en ressources. Dans cette étape, vous utiliserez + touch-reload + pour surveiller les modifications apportées à un fichier particulier et recharger lorsque le fichier est mis à jour ou remplacé.

Pour implémenter cela, commencez par ouvrir votre fichier + uwsgi.ini +:

sudo nano uwsgi.ini

Ensuite, ajoutez la ligne en surbrillance à la fin du fichier:

/var/www/TestApp/uwsgi.ini

module = main
callable = app
master = true

Ceci spécifie un fichier qui sera modifié pour déclencher un rechargement complet de l’application. Une fois les modifications apportées, enregistrez et fermez le fichier.

Pour le démontrer, apportez un léger changement à votre application. Commencez par ouvrir votre fichier + app / views.py +:

sudo nano app/views.py

Remplace la chaîne renvoyée par la fonction + home +:

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

from flask import render_template
from app import app

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

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

Enregistrez et fermez le fichier après avoir apporté une modification.

Ensuite, si vous ouvrez la page d’accueil de votre application à «+ http: //: », vous remarquerez que les modifications ne sont pas reflétées. En effet, la condition de rechargement est une modification du fichier ` uwsgi.ini `. Pour recharger l'application, utilisez ` touch +` pour activer la condition:

sudo touch uwsgi.ini

Rechargez à nouveau la page d’accueil de l’application dans votre navigateur. Vous constaterez que l’application a incorporé les modifications:

image: https: //assets.digitalocean.com/articles/CART-62081/ThereHasBeenAChange.png [page mise à jour]

Dans cette étape, vous configurez une condition + touch-reload + pour mettre à jour votre application après avoir apporté des modifications.

Conclusion

Dans ce didacticiel, vous avez créé et déployé une application Flask dans un conteneur Docker. Vous avez également configuré + touch-reload + pour actualiser votre application sans avoir à redémarrer le conteneur.

Avec votre nouvelle application sur Docker, vous pouvez maintenant évoluer facilement. Pour en savoir plus sur l’utilisation de Docker, consultez leur documentation officielle.