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