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