Aller au contenu principal

Compose

Objectifs​

  • Estimer son travail
  • Créer un Makefile
  • Utiliser Traefik
  • Connecter les services d'un Docker Compose
  • Appliquer les twelve-factor app

Rendu​

  • Rapport individuel en Markdown à rendre avant le prochain cours
    • GitHub Classroom : https://classroom.github.com/a/9OqjgI3Y
    • Nom du fichier : report.md à la racine du répertoire
    • Devoir sur Cyberlearn : mettre le lien de la pull request GitLab dans le champ texte
    • Délai: 1 semaine

Tâches​

Estimer son travail​

  • Estimez le temps nécessaire pour réaliser ce laboratoire
    • Découpez le travail en tâches pour faciliter l'estimation
  • Lorsque vous aurez terminé le laboratoire, comparez le temps estimé avec le temps réellement passé
TâcheTemps estiméTemps réelCommentaire
Estimation10m15m...
............
Total2h1h30...

Git​

  • Reprenez votre projet sur GitLab du laboratoire précédent (HEIG-VD DevOps)
  • Mettez tout votre travail sur une branche feature/03-compose et faites une merge request (MR) sur main en m'ajoutant comme reviewer
  • Séparez votre travail en commits cohérents avec des messages de commit clairs et concis

Créer un Makefile​

  • Créez un Makefile à la racine pour automatiser les tâches suivantes:
    • make install pour installer les dépendances (backend et frontend)
    • make dev-backend pour démarrer le backend en mode développement
    • make dev-frontend pour démarrer le frontend en mode développement
    • make dev-database pour démarrer uniquement la database
  • Indiquez votre démarche dans le rapport

Utiliser Traefik​

Pour éviter des probèmes de CORS avec le frontend, nous allons utiliser Traefik comme reverse proxy afin de servir le frontend et le backend sur le même domaine.

  • Ajoutez Traefik au compose.yml afin de rediriger les requêtes comme suit:
    • Commençant par / vers le frontend
    • Commençant par /api vers le backend
  • Exemple de Docker Compose
  • Utilisez la rule PathPrefix pour rediriger les requêtes vers le bon service
  • Pour le backend, utilisez le StripPrefix afin de supprimer le préfixe /api avant de rediriger la requête
    • Une fois le middleware créé, il faut l'ajouter au service. Voir l'exemple
  • De plus, il faut configurer le root_path de FastAPI pour qu'il corresponde au préfixe /api
    • Afin de pouvoir changer la valeur du root_path grâce à une variable d'environnement, modifiez le fichier main.py comme indiqué ci-dessous:
  • Indiquez votre démarche dans le rapport
/backend/backend/main.py
from typing import Union
from os import getenv

from fastapi import FastAPI

app = FastAPI(root_path=getenv("ROOT_PATH"))

@app.get("/")
def read_root():
return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
Solution compose.yml
compose.yml
services:
reverse-proxy:
image: traefik:v2.10
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
frontend:
labels:
- "traefik.http.routers.frontend.rule=PathPrefix(`/`)"
backend:
labels:
- "traefik.http.routers.backend.rule=PathPrefix(`/api`)"
- "traefik.http.routers.backend.middlewares=backend-stripprefix"
- "traefik.http.middlewares.backend-stripprefix.stripprefix.prefixes=/api"

Connecter le backend à la database​

  • On va utiliser SQLAlchemy pour connecter le backend à la database en suivant la documentation de FastAPI
    • Installez le package sqlalchemy et psycopg2 dans le backend poetry add sqlalchemy psycopg2
    • Créez/modifiez les fichiers suivants dans /backend/backend/ afin d'avoir un service CRUD :
/backend/backend/database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker

# Remplacez les valeurs par les valeurs de votre database
DATABASE_URL = "postgresql://user:password@postgresserver/db"

engine = create_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()
  • Démarrez le backend poetry run uvicorn backend.main:app --reload et testez les endpoints sur http://localhost:8000/docs
  • Vérifiez que le Docker Compose fonctionne toujours docker compose up --build et corrigez au besoin
    • Indiquez vos corrections dans le rapport
  • Modifiez le backend pour qu'il suive les twelve-factors app et configurez-le correctement dans le Docker Compose
    • Utilisez les mêmes variables d'environnement que la database ainsi que leur valeur par défaut
    • Extraire le mot de passe de la database dans un .env pour s'assurer qu'il soit le même dans les deux services
    • Ajoutez une vraie dépendance à la database dans le backend en utilisant un healthcheck, voici un exemple
    • Changez le mot de passe de la database et vérifiez que le backend fonctionne toujours (il faudra peut-être supprimer le volume de la database pour la recréer)
    • Pour lancer le backend en utilisant le .env, on va utiliser python-dotenv
      • poetry add --group dev python-dotenv
      • poetry run dotenv -f ../.env run uvicorn backend.main:app --reload
    • Indiquez vos modifications (autres que celles indiquées) dans le rapport
Solution database.py
/backend/backend/database.py
from os import getenv

from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker

postgres_user = getenv("POSTGRES_USER", "postgres")
postgres_password = getenv("POSTGRES_PASSWORD", "postgres")
postgres_host = getenv("POSTGRES_HOST", "localhost")
postgres_db = getenv("POSTGRES_DB", postgres_user)
DATABASE_URL = (
f"postgresql://{postgres_user}:{postgres_password}@{postgres_host}/{postgres_db}"
)

engine = create_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()
Solution Dockerfile

Il faut ajouter des librairies supplémentaires pour que le backend fonctionne avec PostgreSQL:

/backend/Dockerfile
RUN apk add --no-cache \
musl-dev \
postgresql-dev

Ajoutez un frontend​

  • Dans le dossier /frontend/, ajoutez/modifiez les fichiers suivants afin de configurer les environnements et le proxy :
/frontend/.env
VITE_BACKEND_URL=/api
  • On va utiliser Milligram comme framework CSS :
    • npm install milligram
  • Supprimez tous les fichiers sous /frontend/src/assets/ et /frontend/src/components/
  • Sous /frontend/src/, créez/modifiez les fichiers suivants :
/frontend/src/main.ts
import "milligram/dist/milligram.min.css";

import { createApp } from "vue";
import App from "./App.vue";

createApp(App).mount("#app");
  • Démarrez le frontend npm run dev et testez l'application (avec le backend et la database démarrés)
  • Vérifiez que le Docker Compose fonctionne

Docker Registry​

  • Poussez les images Docker sur le GitLab Registry
    • Documentation
    • Les noms des images sont préfixés par l'adresse du registry (défaut au Docker Hub)
      • Exemple: registry.gitlab.com/username/project/image:tag
    • Doit fonctionner avec docker compose push