Découverte d’une application web flask

wget https://tp-docker.esgi.cloud/TP2/microblog.zip
    sudo apt install python3-pip python3-dev build-essential

<!-- - Changez le prénom Miguel par le vôtre dans l’application. -->
<!-- - Relancez l’app flask et testez la modification en rechargeant la page. -->


Passons à Docker

Déployer une application Flask manuellement à chaque fois est relativement pénible. Pour que les dépendances de deux projets Python ne se perturbent pas, il faut normalement utiliser un environnement virtuel virtualenv pour séparer ces deux apps.
Avec Docker, les projets sont déjà isolés dans des conteneurs. Nous allons donc construire une image de conteneur pour empaqueter l’application et la manipuler plus facilement. Assurez-vous que Docker est installé.

Pour connaître la liste des instructions des Dockerfiles et leur usage, se référer au manuel de référence sur les Dockerfiles.

RUN apt-get update -y
RUN apt-get install -y python3-pip

<!-- - RUN apt-get install -y python3-pip python-dev build-essential -->

COPY ./requirements.txt /requirements.txt
RUN pip3 install -r requirements.txt
ENV FLASK_APP microblog.py
COPY ./ /microblog
WORKDIR /microblog

Cette première ligne indique de copier tout le contenu du dossier courant sur l’hôte dans un dossier /microblog à l’intérieur du conteneur.
Nous n’avons pas copié les requirements en même temps pour pouvoir tirer partie des fonctionnalités de cache de Docker, et ne pas avoir à retélécharger les dépendances de l’application à chaque fois que l’on modifie le contenu de l’app.

Puis, dans la 2e ligne, le dossier courant dans le conteneur est déplacé à /.

CMD ["./boot.sh"]

Docker Hub


Améliorer le Dockerfile

Une image plus simple

Faire varier la configuration en fonction de l’environnement

Le serveur de développement Flask est bien pratique pour debugger en situation de développement, mais n’est pas adapté à la production.
Nous pourrions créer deux images pour les deux situations mais ce serait aller contre l’impératif DevOps de rapprochement du dev et de la prod.

Pour démarrer l’application, nous avons fait appel à un script de boot boot.sh avec à l’intérieur :

#!/bin/bash

# ...

set -e
if [ "$APP_ENVIRONMENT" = 'DEV' ]; then
    echo "Running Development Server"
    exec flask run -h 0.0.0.0
else
    echo "Running Production Server"
    exec gunicorn -b :5000 --access-logfile - --error-logfile - app_name:app
fi


Exposer le port

Dockerfile amélioré

FROM python:3-alpine

COPY ./requirements.txt /requirements.txt
RUN pip3 install -r requirements.txt
ENV FLASK_APP microblog.py

COPY ./ /microblog
WORKDIR /microblog

ENV APP_ENVIRONMENT PROD

EXPOSE 5000

CMD ["./boot.sh"]

L’instruction HEALTHCHECK

HEALTHCHECK permet de vérifier si l’app contenue dans un conteneur est en bonne santé.

FROM python:alpine

RUN apk add curl
RUN pip install flask==0.10.1

ADD /app.py /app/app.py
WORKDIR /app

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit 1

CMD python app.py
from flask import Flask

healthy = True

app = Flask(__name__)

@app.route('/health')
def health():
    global healthy

    if healthy:
        return 'OK', 200
    else:
        return 'NOT OK', 500

@app.route('/kill')
def kill():
    global healthy
    healthy = False
    return 'You have killed your app.', 200


if __name__ == "__main__":
    app.run(host="0.0.0.0")

Facultatif : Décortiquer une image

Une image est composée de plusieurs layers empilés entre eux par le Docker Engine et de métadonnées.


Facultatif : un Registry privé


Facultatif : Faire parler la vache

Créons un nouveau Dockerfile qui permet de faire dire des choses à une vache grâce à la commande cowsay.
Le but est de faire fonctionner notre programme dans un conteneur à partir de commandes de type :


Facultatif : Un multi-stage build

Transformez le Dockerfile de l’app dnmonster située à l’adresse suivante pour réaliser un multi-stage build afin d’obtenir l’image finale la plus légère possible :
https://github.com/amouat/dnmonster/

La documentation pour les multi-stage builds est à cette adresse : https://docs.docker.com/develop/develop-images/multistage-build/