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
  • Délai: 1 semaine

Tâches

Estimer son travail

  • Estimer le temps nécessaire pour réaliser ce travail.
    • Découper le travail en tâches pour faciliter l'estimation.
  • Une fois terminé, comparer le temps estimé avec le temps réellement passé.
TâcheTemps estiméTemps passéCommentaire
Estimation10m15m...
............
Total2h1h30...

Git

  • Reprendre son projet GitLab du laboratoire précédent (DOP Python).
  • Travailler sur une nouvelle branche feature/03-compose.
    • Faire une merge request (MR) sur main une fois terminé et demander une revue.
    • Une fois qu'une MR est acceptée, la merge sur main.
  • Séparer son travail en commits cohérents avec des messages de commit clairs et concis.

Créer un Makefile

  • Créer 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.
Question rapport

Indiquer sa démarche.

Utiliser Traefik

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

  • Ajouter 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
  • Utiliser la rule PathPrefix pour rediriger les requêtes vers le bon service.
  • Pour le backend, utiliser le StripPrefix afin de supprimer le préfixe /api avant de rediriger la requête.
    • Une fois le middleware créé, l'ajouter au service. Voir l'exemple.
  • 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, modifier le fichier main.py comme indiqué ci-dessous :
Question rapport

Indiquer sa démarche.

/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

  • Utiliser SQLAlchemy pour connecter le backend à la database en suivant la documentation de FastAPI.
    • Installer le package sqlalchemy et psycopg2 dans le backend. poetry add sqlalchemy psycopg2
    • Créer ou modifier 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émarrer le backend poetry run uvicorn backend.main:app --reload et tester les endpoints sur http://localhost:8000/docs
  • Vérifier que le Docker Compose fonctionne toujours docker compose up --build et corriger au besoin.
  • Modifier le backend pour qu'il suive les twelve-factors app et le configurer correctement dans le Docker Compose.
    • Utiliser 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.
    • Ajouter une vraie dépendance à la database dans le backend en utilisant un healthcheck, voici un exemple.
    • Changer le mot de passe de la database et vérifier 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, utiliser python-dotenv :
      • poetry add --group dev python-dotenv
      • poetry run dotenv -f ../.env run uvicorn backend.main:app --reload
Question rapport

Indiquer ses corrections et/ou modifications (sauf les indications).

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

Ajouter des librairies supplémentaires pour que le backend fonctionne avec PostgreSQL :

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

Ajouter un frontend

  • Dans le dossier /frontend/, ajouter ou modifier 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émarrer le frontend npm run dev et tester l'application (avec le backend et la database démarrés)
  • Vérifier que le Docker Compose fonctionne

Docker Registry

  • Pousser 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