Ajout du TP n°4
This commit is contained in:
		
							
								
								
									
										29
									
								
								TP4/QUESTIONS.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								TP4/QUESTIONS.md
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
				
			||||||
							
								
								
									
										6
									
								
								TP4/meme-app/backend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								TP4/meme-app/backend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -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"]
 | 
				
			||||||
							
								
								
									
										37
									
								
								TP4/meme-app/backend/app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								TP4/meme-app/backend/app.py
									
									
									
									
									
										Normal file
									
								
							@@ -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"}
 | 
				
			||||||
							
								
								
									
										5
									
								
								TP4/meme-app/backend/requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								TP4/meme-app/backend/requirements.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					fastapi==0.68.0
 | 
				
			||||||
 | 
					uvicorn[standard]==0.15.0
 | 
				
			||||||
 | 
					python-multipart
 | 
				
			||||||
 | 
					pymongo==3.12.0
 | 
				
			||||||
 | 
					websockets==10.0
 | 
				
			||||||
							
								
								
									
										38
									
								
								TP4/meme-app/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								TP4/meme-app/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							@@ -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:
 | 
				
			||||||
							
								
								
									
										3
									
								
								TP4/meme-app/frontend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								TP4/meme-app/frontend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
							
								
								
									
										49
									
								
								TP4/meme-app/frontend/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								TP4/meme-app/frontend/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <title>Meme Gallery</title>
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					        .meme { margin: 10px; padding: 10px; border: 1px solid #ccc; }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <h1>Meme Gallery</h1>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					        <h2>Add a Meme</h2>
 | 
				
			||||||
 | 
					        <input type="text" id="title" placeholder="Title">
 | 
				
			||||||
 | 
					        <input type="text" id="url" placeholder="Image URL">
 | 
				
			||||||
 | 
					        <button onclick="addMeme()">Add Meme</button>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div id="memes"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					        async function loadMemes() {
 | 
				
			||||||
 | 
					            const response = await fetch('/backend/memes');
 | 
				
			||||||
 | 
					            const data = await response.json();
 | 
				
			||||||
 | 
					            const memesDiv = document.getElementById('memes');
 | 
				
			||||||
 | 
					            memesDiv.innerHTML = data.memes.map(meme => `
 | 
				
			||||||
 | 
					                <div class="meme">
 | 
				
			||||||
 | 
					                    <h3>${meme.title}</h3>
 | 
				
			||||||
 | 
					                    <img src="${meme.url}" width="200">
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            `).join('');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        async function addMeme() {
 | 
				
			||||||
 | 
					            const title = document.getElementById('title').value;
 | 
				
			||||||
 | 
					            const url = document.getElementById('url').value;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            await fetch('/backend/memes?' + new URLSearchParams({
 | 
				
			||||||
 | 
					                title: title,
 | 
				
			||||||
 | 
					                url: url
 | 
				
			||||||
 | 
					            }), {method: 'POST'});
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            loadMemes();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loadMemes();
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										18
									
								
								TP4/meme-app/frontend/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								TP4/meme-app/frontend/nginx.conf
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										105
									
								
								TP4/tp4-cheat-sheet.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								TP4/tp4-cheat-sheet.md
									
									
									
									
									
										Normal file
									
								
							@@ -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`)
 | 
				
			||||||
							
								
								
									
										236
									
								
								TP4/tp4.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								TP4/tp4.md
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <title>Meme Gallery</title>
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					        .meme { margin: 10px; padding: 10px; border: 1px solid #ccc; }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <h1>Meme Gallery</h1>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					        <h2>Add a Meme</h2>
 | 
				
			||||||
 | 
					        <input type="text" id="title" placeholder="Title">
 | 
				
			||||||
 | 
					        <input type="text" id="url" placeholder="Image URL">
 | 
				
			||||||
 | 
					        <button onclick="addMeme()">Add Meme</button>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div id="memes"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					        async function loadMemes() {
 | 
				
			||||||
 | 
					            const response = await fetch('/backend/memes');
 | 
				
			||||||
 | 
					            const data = await response.json();
 | 
				
			||||||
 | 
					            const memesDiv = document.getElementById('memes');
 | 
				
			||||||
 | 
					            memesDiv.innerHTML = data.memes.map(meme => `
 | 
				
			||||||
 | 
					                <div class="meme">
 | 
				
			||||||
 | 
					                    <h3>${meme.title}</h3>
 | 
				
			||||||
 | 
					                    <img src="${meme.url}" width="200">
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            `).join('');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        async function addMeme() {
 | 
				
			||||||
 | 
					            const title = document.getElementById('title').value;
 | 
				
			||||||
 | 
					            const url = document.getElementById('url').value;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            await fetch('/backend/memes?' + new URLSearchParams({
 | 
				
			||||||
 | 
					                title: title,
 | 
				
			||||||
 | 
					                url: url
 | 
				
			||||||
 | 
					            }), {method: 'POST'});
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            loadMemes();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loadMemes();
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user