Skip to content

Latest commit

 

History

History
256 lines (177 loc) · 10.5 KB

File metadata and controls

256 lines (177 loc) · 10.5 KB

TD n°3 - Conteneurisation

Les notions abordées durant ce TD seront liées à docker, à docker-compose et à la sécurité des conteneurs.

Simple application

Nous allons construire une simple application frontend / backend et les conteneuriser.

Backend

Commençons par un coeur de d'application, en utilisant Flask, qui va dans un premier temps réponde Hello, World! lors d'un appel sur la route /.

Prérequis

Si ce n'est pas déjà fait:

  1. Installer python3 et pip3

     sudo apt install python3
     sudo apt install python3-pip
  2. Installer Flask, Flask est un framework web léger écrit en Python. Il permet de créer rapidement des applications web ou des API REST, un peu comme Express.js pour Node.js.

    pip3 install flask
  3. Créer dans votre dépôt un dossier backend et un dossier frontend.

Implementation

Dans le dossier backend, créer un fichier server.py contenant l'implementation d'un serveur Flask (documentation: Flask).

Vous devriez pouvoir exécuter le serveur avec la commande: flask --app server.py run

Accéder à votre serveur via votre navigateur à l'addresse http://localhost:5000. Vous venez de créer votre premier serveur 🚀

Tip

Si vous utilisez CodeSpace, suivez le lien qui s'affiche dans la pop-up en bas à droite.

Ajoutez des endpoints (route) supplémentaires:

  • La route / renverra désormais une chaine de caractère de votre choix (e.g. Hello, ceci est un compteur avec la liste des routes disponibles)
  • La route /cpt renvoie la valeur d'un compteur stocké en variable locale.
  • La route /incr incrémente du compteur stocké en variable locale.
  • La route /decr decrémente du compteur stocké en variable locale.

Testez tous ces endpoints localement avec la commande: flask run.

Conteneurisation

Nous allons utiliser docker pour conteneuriser ce backend: Les commmandes Docker

Créez votre premier Dockerfile.

  • Image de base pour l'environnement: alpine:3.22.2 (cf. Docker Image)

    Le manager de packet de alpine est apk, ajouter des packets avec la commande apk add flask

  • Copier le fichier server.py dans le conteneur.
  • Le port d'exposition est le 5000.
  • La comande de lancement du conteneur devrait être : flask run

Testez le avec la commande docker build . ( l'option -t backend vous permettra de donner un nom à la machine et donc de la retrouver et l'utiliser plus facilement)

Warning

Attention, nous construisons un environnement d'execution dédié, toutes les librairies installées locallement sont à ajouter au Dockefile.

Executer le conteneur et verifier son fonctionnement.

Frontend

Nous allons maintenant mettre en place un frontend qui va s'interfacer avec notre backend.

Implémentation

Nous allons l'implémenter via la stack HTML/CSS/JS.

  1. Dans le dossier frontend, créez les fichiers suivants : index.html, app.js
  2. Servez le dossier frontend en ouvrant le fichier index.html avec un navigateur ou avec l’extension Live Server de VS Code.

Si rien ne se passe, accéder à la console de votre navigateur avec F12.

Note

Si vos requêtes fetch sont bloquées, verifiez que vous autorisez bien les CORS côté Flask (backend) :

# backend/server.py
from flask_cors import CORS
CORS(app)

si nécessaire : Installez flask-cors via pip install flask-cors.

Le fichier index.html doit contenir une page avec :

  • Un titre et un court texte rappelant les routes disponibles.
  • Un bloc Compteur avec :
    • l’affichage de la valeur,
    • un bouton +1 (incrément),
    • un bouton −1 (décrément),
    • un bouton Rafraîchir (relecture depuis /cpt).
  • Un espace Status pour afficher “Chargement…”, “OK”, ou un message d’erreur.

Tip

Les fichiers .html peuvent être ouvert avec un navigateur web pour en voir le contenu.

Vous pouvez prendre un peu de temps pour faire de la mise en forme via CSS.

Conteneurisation

Conteneuriser le frontend and un conteneur serveur web simple. Dans un dossier frontend, exécuter les actions suivantes :

  1. Nous allons utiliser nginx pour servir cette page. ( cf. Liens utiles ).
    Créer un Dockerfile qui se base sur la dernière version de l'image nginx.

  2. Ajouter les fichiers au conteneur via le paramêtre COPY.

     COPY index.html /usr/share/nginx/html/
     # Si vous avez d'autres fichiers ou dossier, copier les également
     COPY ./img /usr/share/nginx/html
  3. Préciser le port d'ouverture du conteneur via le paramètre EXPOSE, il s'agit du port servi par nginx ( 80 par défaut ).

Quel est le point d'entrée de l'application ? Quelle commande va s'executer au démarrage du conteneur ?

  1. Nous avons décrit notre conteneur, construiser maintenant l'image de ce conteneur via la commande docker build.
  2. Executer votre conteneur via docker run.

Via un navigateur, tester votre frontend conteneurisé 🚀

Tip

Des difficultés à y acceder ? vérifié que le conteneur en execution est bien associé à une port de votre machine. (cf. Les commmandes Docker)


Important

Le lancement de tous les conteneurs sur votre machine via docker run doit vous permettre d'utiliser le compteur dans votre navigateur.


docker-compose

Nous allons utiliser docker-compose pour unifié le déploiement d'une ensemble de conteneur sur votre machine.

Nous reprendrons les images exécutées dans le projet de l'exercice précédent pour déployer localement et en une commande l'architecture suivante :

graph LR
    F["Frontend
        API_URL='localhost:5000'"] --> B["API
                                        REDIS_URL='localhost'
                                        REDIS_PORT='6379'"]
    B --> R[(Redis DB)]
Loading

Mise en place

Voici un template de fichier compose.yaml utilisé par la commande docker compose up :

services:
  frontend:
    image: <image>
    ports:
      - "<port-hote>:<port-ctn>"
    environment:
      - <key>=<value>
    networks:
      - myapp-network

  backend:
    <to-do-for-backend>
  <other-services>
networks:
  # La présence de la ligne suivante suffit pour demander la création du réseau.
  myapp-network: {}

À partir du template ci-dessus et de la documentation :

  1. Dans un dossier td-conteneurisation, créer un fichier compose.yaml.

  2. Le parametre image correspond aux images suivi du tag (image:tag) que vous avez construit dans l'exercice précédent.

  3. Définissez, pour chaque conteneur de l'architecture, un service dans le tableau services.

  4. Validez le l'architecture en la démarrant localement avec la commande:

    docker compose up

    Vous pouvez arrêter les différents conteneurs en une commande : docker compose down

  5. Rendez-vous sur http://localhost:8080 👈

Note

Le réseau virtuel myapp-network, dans lequel vont s'incrire ces conteneurs, n'a pas besoin paramètre supplémentaire.

Du build au déploiement

docker-compose permet également d'unifié le dévelopement des différents tiers de l'application.

  1. Dans le dossier td-conteneurisation, créer un dossier frontend et backend.

  2. Ajouter les codes et les Dockerfile du frontend et de l'API du projet Virtualization Cloud Computing dans ces dossiers.

  3. Pour chacun des services définis dans le fichier compose.yaml, ajouter l'argument build qui permet de definir où se trouvent les fichiers sources des différents services de la composition.

        # ...
        frontend:
          build:
            context: ./frontend/                      # Dossier d'exécution du `docker build`
            dockerfile: frontend/Dockerfile           # Dockerfile à utiliser pour l'exécution du `docker build`
        # ...
  4. Contruiser tous les conteneurs en une seule fois en utilisant la commande :

        docker compose build

Sécurité des conteneurs

Trivy

Trivy est un outil de scan d'image qui permet d'identifier les vulnérabilités d'une configuration.

En vous basant sur la documentation de l'outil, installer l'outil en suivant les étapes recommandées pour votre système.

Trivy s'utilise sur des configurations (Kubernetes, Terraform, etc) et des images en suivant le format de commande suivant:

trivy <target> [--scanners <scanner1,scanner2>] <subject>

Nous allons scanner notre première image, utiliser trivy pour scanner l'image python:3.4-alpine.

trivy image python:3.4-alpine

Que pouvez-vous observer ?

Nous allons maintenant scanner les images construites dans la parties précédentes.

  1. Construiser les images de conteneur frontend et backend à partir de leur Dockerfile et scanner ces images.
  2. Résolver les vulnérabilités identifiées par trivy.
  3. Reconstruiser et rescanner vos images, si des vulnérabilités sont listées, reprennez à l'étape 2.

Un dernier test pour la route

Scanner l'ensemble des fichiers du dossier de votre dépôt en local avec trivy.

Tip

Un ensemble de fichiers et de dossiers avec une racine commune est aussi appelé "système de fichier" qui se traduit par "File System" en anglais et s'abrège fs.

Bonus - Tout ça en plus simple

Trivy dispose d'une GitHub Action ! Via les informations de ce dépôt et le Market Place des GitHub Action. Mettez en place sur votre dépôt une GitHub Action qui scan les images issues de vos Dockerfiles.


Liens utiles