From 2b4bb321e2e1ee90bba417e41975ee43c2d89261 Mon Sep 17 00:00:00 2001 From: stiti Date: Wed, 9 Apr 2025 11:55:41 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20du=20TP=20n=C2=B04?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TP4/QUESTIONS.md | 29 ++++ TP4/meme-app/backend/Dockerfile | 6 + TP4/meme-app/backend/app.py | 37 ++++ TP4/meme-app/backend/requirements.txt | 5 + TP4/meme-app/docker-compose.yml | 38 +++++ TP4/meme-app/frontend/Dockerfile | 3 + TP4/meme-app/frontend/index.html | 49 ++++++ TP4/meme-app/frontend/nginx.conf | 18 ++ TP4/tp4-cheat-sheet.md | 105 ++++++++++++ TP4/tp4.md | 236 ++++++++++++++++++++++++++ 10 files changed, 526 insertions(+) create mode 100644 TP4/QUESTIONS.md create mode 100644 TP4/meme-app/backend/Dockerfile create mode 100644 TP4/meme-app/backend/app.py create mode 100644 TP4/meme-app/backend/requirements.txt create mode 100644 TP4/meme-app/docker-compose.yml create mode 100644 TP4/meme-app/frontend/Dockerfile create mode 100644 TP4/meme-app/frontend/index.html create mode 100644 TP4/meme-app/frontend/nginx.conf create mode 100644 TP4/tp4-cheat-sheet.md create mode 100644 TP4/tp4.md diff --git a/TP4/QUESTIONS.md b/TP4/QUESTIONS.md new file mode 100644 index 0000000..9c1f1dc --- /dev/null +++ b/TP4/QUESTIONS.md @@ -0,0 +1,29 @@ +Lien meme de test : https://ichef.bbci.co.uk/ace/standard/976/cpsprodpb/16620/production/_91408619_55df76d5-2245-41c1-8031-07a4da3f313f.jpg +Lien URL serveur : http://localhost/index.html + + +# Configuration Docker Compose + +## Liens utiles +- Lien meme de test : https://ichef.bbci.co.uk/ace/standard/976/cpsprodpb/16620/production/_91408619_55df76d5-2245-41c1-8031-07a4da3f313f.jpg +- Lien URL serveur : http://localhost/index.html + +## Quels services doivent communiquer entre eux ? +- Le frontend doit communiquer avec le backend pour récupérer et envoyer les données des mèmes +- Le backend doit communiquer avec MongoDB pour stocker et récupérer les données +- Le frontend n'a pas besoin de communiquer directement avec MongoDB (isolation de sécurité) + +## Quels ports doivent être exposés ? +- Port 80 : exposé par le frontend pour l'accès web public +- Port 8000 : exposé par le backend pour le développement et le débogage (optionnel en production) +- Le port de MongoDB (27017) ne doit pas être exposé à l'extérieur pour des raisons de sécurité + +## Comment assurer la persistance des données ? +- Utiliser un volume Docker nommé (`mongo-data`) attaché au service MongoDB +- Configurer ce volume avec `driver: local` pour un stockage sur la machine hôte +- Conserver ce volume lors des redémarrages avec `docker-compose down` sans l'option `-v` + +## Dans quel ordre les services doivent-ils démarrer ? +1. MongoDB doit démarrer en premier (base de données) +2. Le backend doit démarrer après MongoDB (pour pouvoir s'y connecter) +3. Le frontend doit démarrer après le backend (pour pouvoir accéder à l'API) \ No newline at end of file diff --git a/TP4/meme-app/backend/Dockerfile b/TP4/meme-app/backend/Dockerfile new file mode 100644 index 0000000..9f5df16 --- /dev/null +++ b/TP4/meme-app/backend/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.9-slim +WORKDIR /app +COPY requirements.txt . +RUN pip install -r requirements.txt +COPY . . +CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/TP4/meme-app/backend/app.py b/TP4/meme-app/backend/app.py new file mode 100644 index 0000000..91b2d9a --- /dev/null +++ b/TP4/meme-app/backend/app.py @@ -0,0 +1,37 @@ +from fastapi import FastAPI +from pymongo import MongoClient +from fastapi.middleware.cors import CORSMiddleware + +app = FastAPI() + +# Juste après la déclaration FastAPI() +# Ajouter le middleware CORS +origins = [ + "http://localhost", + "http://localhost:80", + "http://frontend", + "http://frontend:80" +] + +app.add_middleware( + CORSMiddleware, + allow_origins=origins, # Liste des origines autorisées + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# MongoDB connection +client = MongoClient("mongodb://mongodb:27017/") +db = client.memes_db + +@app.get("/memes") +def get_memes(): + memes = list(db.memes.find({}, {"_id": 0})) + return {"memes": memes} + +@app.post("/memes") +def create_meme(title: str, url: str): + meme = {"title": title, "url": url} + db.memes.insert_one(meme) + return {"message": "Meme added successfully"} \ No newline at end of file diff --git a/TP4/meme-app/backend/requirements.txt b/TP4/meme-app/backend/requirements.txt new file mode 100644 index 0000000..0c7fadc --- /dev/null +++ b/TP4/meme-app/backend/requirements.txt @@ -0,0 +1,5 @@ +fastapi==0.68.0 +uvicorn[standard]==0.15.0 +python-multipart +pymongo==3.12.0 +websockets==10.0 \ No newline at end of file diff --git a/TP4/meme-app/docker-compose.yml b/TP4/meme-app/docker-compose.yml new file mode 100644 index 0000000..1935975 --- /dev/null +++ b/TP4/meme-app/docker-compose.yml @@ -0,0 +1,38 @@ +version: '3' +services: + mongodb: + image: mongo:latest + volumes: + - mongo-data:/data/db + networks: + - backend-network + + backend: + build: ./backend + depends_on: + - mongodb + environment: + - MONGO_URI=mongodb://mongodb:27017/ + networks: + - backend-network + - frontend-network + ports: + - "8000:8000" + + frontend: + build: ./frontend + depends_on: + - backend + networks: + - frontend-network + ports: + - "80:80" + +volumes: + mongo-data: + driver: local + +# Pour la sécurité, c'est mieux d'avoir deux réseaux (vu en CM) -> même si dans notre cas ce n'est pas utile +networks: + backend-network: + frontend-network: \ No newline at end of file diff --git a/TP4/meme-app/frontend/Dockerfile b/TP4/meme-app/frontend/Dockerfile new file mode 100644 index 0000000..1c0275d --- /dev/null +++ b/TP4/meme-app/frontend/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:alpine +COPY index.html /usr/share/nginx/html/index.html +COPY nginx.conf /etc/nginx/conf.d/default.conf \ No newline at end of file diff --git a/TP4/meme-app/frontend/index.html b/TP4/meme-app/frontend/index.html new file mode 100644 index 0000000..e2d281a --- /dev/null +++ b/TP4/meme-app/frontend/index.html @@ -0,0 +1,49 @@ + + + + Meme Gallery + + + +

Meme Gallery

+ +
+

Add a Meme

+ + + +
+ +
+ + + + \ No newline at end of file diff --git a/TP4/meme-app/frontend/nginx.conf b/TP4/meme-app/frontend/nginx.conf new file mode 100644 index 0000000..3f3e20f --- /dev/null +++ b/TP4/meme-app/frontend/nginx.conf @@ -0,0 +1,18 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html; + } + + location /backend/ { + proxy_pass http://backend:8000/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} \ No newline at end of file diff --git a/TP4/tp4-cheat-sheet.md b/TP4/tp4-cheat-sheet.md new file mode 100644 index 0000000..d8c353c --- /dev/null +++ b/TP4/tp4-cheat-sheet.md @@ -0,0 +1,105 @@ +# Docker Compose - Aide-mémoire + +## Commandes Essentielles + +### Démarrage et Arrêt +```bash +# Démarrer les services +docker compose up -d # Mode détaché (arrière-plan) +docker compose up # Mode interactif (voir les logs) + +# Arrêter les services +docker compose down # Arrête et supprime les conteneurs +docker compose stop # Arrête sans supprimer +``` + +### Logs et Surveillance +```bash +# Voir les logs +docker compose logs # Tous les logs +docker compose logs -f # Suivre les logs en direct +docker compose logs [service] # Logs d'un service spécifique + +# État des conteneurs +docker compose ps # Liste et état des conteneurs +``` + +### Construction et Reconstruction +```bash +# Construire les images +docker compose build # Tous les services +docker compose build [service] # Un service spécifique + +# Reconstruction et démarrage +docker compose up -d --build # Reconstruire puis démarrer +``` + +## Structure docker-compose.yml + +### Services +```yaml +services: + monservice: + image: ... # Utiliser une image existante + build: ... # Construire depuis un Dockerfile + ports: # Exposer des ports + volumes: # Monter des volumes + depends_on: # Définir des dépendances + networks: # Connecter aux réseaux +``` + +### Réseaux +```yaml +networks: + monreseau: # Réseau simple + monreseau_interne: + internal: true # Réseau isolé +``` + +### Volumes +```yaml +volumes: + monvolume: # Volume pour persistance +``` + +## Commandes Utiles + +### Inspection +```bash +# Vérifier la configuration +docker compose config # Valider le fichier compose + +# Voir les réseaux +docker network ls # Lister les réseaux +docker network inspect [réseau] # Détails d'un réseau + +# Voir les volumes +docker volume ls # Lister les volumes +``` + +### Debug +```bash +# Accéder à un conteneur +docker compose exec [service] sh # Ouvrir un shell + +# Voir les processus +docker compose top # Processus en cours +``` + +### Gestion des Services +```bash +# Redémarrer des services +docker compose restart # Tous les services +docker compose restart [service] # Un service spécifique + +# Recréer des conteneurs +docker compose up -d --force-recreate +``` + +## Conseils + +- Utilisez toujours `-d` en production, jamais en développement +- Pensez à vérifier les logs en cas de problème +- `docker compose config` est votre ami pour valider la syntaxe +- Les réseaux se créent automatiquement +- Les volumes persistent après un `down` (sauf si `-v`) diff --git a/TP4/tp4.md b/TP4/tp4.md new file mode 100644 index 0000000..eddceb0 --- /dev/null +++ b/TP4/tp4.md @@ -0,0 +1,236 @@ +# TP4 Docker Compose - Application de Mèmes +### Objectif +Créer une application web de partage de mèmes en utilisant Docker Compose pour orchestrer 3 conteneurs : +- Un frontend (nginx) +- Un backend (Python/FastAPI) +- Une base de données (MongoDB) + +### Prérequis +- Docker et Docker Compose installés +- Un éditeur de code (VS Code recommandé) + +### Structure du projet +``` +meme-app/ +├── backend/ +│ ├── Dockerfile +│ ├── requirements.txt +│ └── app.py +├── frontend/ +│ ├── Dockerfile +│ ├── nginx.conf +│ └── index.html +└── docker-compose.yml +``` + +### Étape 1 : Mise en place de la structure +```bash +# Créer l'arborescence +mkdir meme-app +cd meme-app +mkdir backend frontend +touch docker-compose.yml +``` + +### Étape 2 : Backend + +1. Créer backend/requirements.txt : +``` +fastapi==0.68.0 +uvicorn[standard]==0.15.0 +python-multipart +pymongo==3.12.0 +websockets==10.0 +``` + +2. Créer backend/app.py : +```python +from fastapi import FastAPI +from pymongo import MongoClient + +app = FastAPI() + +# MongoDB connection +client = MongoClient("mongodb://mongodb:27017/") +db = client.memes_db + +@app.get("/memes") +def get_memes(): + memes = list(db.memes.find({}, {"_id": 0})) + return {"memes": memes} + +@app.post("/memes") +def create_meme(title: str, url: str): + meme = {"title": title, "url": url} + db.memes.insert_one(meme) + return {"message": "Meme added successfully"} +``` + +- Ajout support CORS sur le backend : + Dans les imports: +```py +from fastapi.middleware.cors import CORSMiddleware + +# Juste après la déclaration FastAPI() +# Ajouter le middleware CORS +origins = [ + "http://localhost", +] + +app.add_middleware( + CORSMiddleware, + allow_origins=origins, # Liste des origines autorisées + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) +``` + +- Attention nom du service à remplacer dans le back : +```py +client = MongoClient("mongodb://mongodb:27017/") +``` +Le 2e "mongodb" correspond au nom du service de MongoDB + +3. Créer backend/Dockerfile : +```dockerfile +FROM python:3.9-slim +WORKDIR /app +COPY requirements.txt . +RUN pip install -r requirements.txt +COPY . . +CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] +``` + +### Étape 3 : Frontend + +1. Créer frontend/index.html : +```html + + + + Meme Gallery + + + +

Meme Gallery

+ +
+

Add a Meme

+ + + +
+ +
+ + + + +``` + +2. Créer frontend/nginx.conf : +```nginx +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html; + } + + location /backend/ { + proxy_pass http://backend:8000/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} +``` + +- exposer sur un port le backend + +Modification du front des URL +`http://localhost:PORT_BACK/memes` + +3. Créer frontend/Dockerfile : +```dockerfile +FROM nginx:alpine +COPY index.html /usr/share/nginx/html/index.html +COPY nginx.conf /etc/nginx/conf.d/default.conf +``` + +### Étape 4 : Docker Compose + +Votre mission : Créer le fichier docker-compose.yml pour : +1. Démarrer MongoDB +2. Démarrer le backend Python en le connectant à MongoDB +3. Démarrer le frontend Nginx en le connectant au backend +4. Gérer les réseaux pour isoler MongoDB +5. Configurer un volume pour les données MongoDB + +Points à considérer : +- Quels services doivent communiquer entre eux ? +- Quels ports doivent être exposés ? +- Comment assurer la persistance des données ? +- Dans quel ordre les services doivent-ils démarrer ? + +### Étape 5 : Tests (30 min) + +1. Démarrer l'application : +```bash +docker compose up -d +``` + +2. Vérifier que tout fonctionne : +- Ouvrir http://localhost dans le navigateur +- Ajouter un mème (utilisez une URL d'image depuis le web) +- Vérifier qu'il s'affiche dans la galerie + +3. Tester la persistance : +```bash +docker compose down +docker compose up -d +``` +Les memes doivent toujours être là ! + +### Rendu attendu +- Le fichier docker-compose.yml complet et fonctionnel +- Une explication de vos choix de configuration +- Un exemple de mème ajouté via l'interface + +### Pour aller plus loin +- Ajoutez des variables d'environnement pour la configuration +- Implémentez un healthcheck pour MongoDB +- Configurez un backup automatique de la base de données \ No newline at end of file