Skip to main content

TP 2 - Docker Compose : Node + MongoDB + React


Vous ne devez pas utiliser l’AI. La politique sur le plagiat s’applique.

Vous devriez être en mesure de faire ce TP qu’avec le contenu de ce site.

Dans ce TP, vous allez :

  1. Créer un projet contenant trois services :

    • backend : API Node.js (avec un Dockerfile)
    • database : MongoDB
    • frontend : application React
  2. Utiliser un docker-compose.yaml pour orchestrer les trois services.

  3. Injecter des données dans MongoDB via un script Node.js.

  4. Vérifier que les conteneurs communiquent entre eux.


Structure du projet

Vous devez créer la structure suivante :

tp2-docker/
│
├── backend/
│   ├── Dockerfile
│   ├── package.json
│   ├── index.js
│   └── seed.js   # script d’injection de données
│
├── frontend/
│   └── (fichiers React créés par create-react-app)
│
└── docker-compose.yaml

Partie 1 — Préparer le backend Node.js

1. Créer le dossier

mkdir -p tp2-docker/backend
cd tp2-docker/backend

2. Créer package.json

{
  "name": "backend",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "seed": "node seed.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "mongodb": "^6.0.0",
    "cors": "^2.8.5"
  }
}

3. Créer index.js (API simple)

const express = require("express");
const { MongoClient } = require("mongodb");
const cors = require("cors"); // 1. Importer cors

const app = express();
app.use(cors()); // 2. Activer les requêtes cross-origin

const url = "mongodb://database:27017";
const client = new MongoClient(url);

async function main() {
  await client.connect();
  const db = client.db("cours");
  const collection = db.collection("etudiants");

  app.get("/", (req, res) => {
    res.json({ message: "API Node.js fonctionne !" });
  });

  app.get("/etudiants", async (req, res) => {
    try {
      const data = await collection.find().toArray();
      res.json(data);
    } catch (err) {
      res.status(500).json({ error: "Erreur lors de la récupération" });
    }
  });

  app.listen(5000, () => console.log("Backend démarré sur le port 5000"));
}

main();

4. Créer seed.js (injection de données)

const { MongoClient } = require("mongodb");

// Connexion au service "database" défini dans docker-compose
const client = new MongoClient("mongodb://database:27017");

async function run() 
{
  await client.connect();

  const db = client.db("cours");
  const collection = db.collection("etudiants");

  // Données de test
  await collection.deleteMany({});

  await collection.insertMany([
    { nom: "Alice", programme: "Informatique" },
    { nom: "Bob", programme: "Réseaux" },
    { nom: "Charlie", programme: "Développement" }
  ]);

  console.log("Données insérées !");
  await client.close();
}

run();

5. Créer le Dockerfile du backend

Le Dockerfile devrait donner ce résultat :

docker run --rm -it \
  -p 5000:5000 \
  -v $(pwd):/app \
  -w /app \
  node:18 \
  sh -c "npm install && npm start"
Important : Dans le Dockerfile, tu dois ajouter obligatoirement la ligne de commentaire suivante tout au début du fichier : "# Dockerfile 2.0".

En lien avec la commande Docker met les étapes en dessous de chacune des lignes de commentaires dans le fichier Dockerfile. Important : Dans le Dockerfile, tu dois ajouter obligatoirement la ligne de commentaire suivante tout au début du fichier : “# Dockerfile 2.0”.

# Image Node officielle (ajouter en dessous la commande)


# Dossier de travail dans le conteneur (ajouter en dessous la commande)


# Copier package.json (ajouter en dessous la commande)


# Installer les dépendances (rien à inscrire)
RUN npm install


# Copier le reste du code (rien à inscrire)
COPY . .

# Exposer le port de l'API (ajouter en dessous la commande)


# Commande de démarrage de node
CMD ["npm", "start"]

Partie 2 — Préparer le frontend React

1. Créer le dossier

cd ..
mkdir frontend
cd frontend

2. Créer l’application React

installer nodejs et npm

sudo apt update
sudo apt install nodejs npm -y

Vérifier que tout est bien installé

node --version
npm --version
npx --version

Création du projet react

npx create-react-app .

3. Modifier le fichier src/App.js

import { useState, useEffect } from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  const [etudiants, setEtudiants] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('http://localhost:5000/etudiants')
      .then((response) => response.json())
      .then((data) => {
        setEtudiants(data);
        setLoading(false);
      })
      .catch((error) => {
        console.error('Erreur de chargement :', error);
        setLoading(false);
      });
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>Frontend React fonctionne pour mon TP2 !</h1>

        {/* Tableau des étudiants ajouté sous la ligne demandée */}
        <div style={{ marginTop: '20px', marginBottom: '20px' }}>
          <h2>Liste des Étudiants</h2>
          {loading ? (
            <p>Chargement des étudiants...</p>
          ) : (
            <table border="1" cellPadding="8" style={{ borderCollapse: 'collapse', color: '#fff', borderColor: '#61dafb', margin: '0 auto' }}>
              <thead>
                <tr>
                  <th>ID</th>
                  <th>Informations / Nom</th>
                </tr>
              </thead>
              <tbody>
                {etudiants.map((etudiant) => (
                  <tr key={etudiant._id}>
                    <td>{etudiant._id}</td>
                    <td>{etudiant.nom ? `${etudiant.nom} ${etudiant.prenom || ''}` : JSON.stringify(etudiant)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

Partie 3 — Créer et compléter le fichier docker-compose.yaml

Dans tp2-docker/, créez ce fichier Docker Compose

Compléter les lignes où il est écrit :

  • # Ajouter la ou les lignes :
  • # rep :
Important : Dans le Docker Compose, tu dois mettre obligatoirement à la ligne de commentaire "Base de données MongoDB" pour "Base de données MongoDB 6.0"
version: "3.8"
services:
  # -------------------------
  # Base de données MongoDB
  # -------------------------
  database:
    # Ajouter la ou les lignes : l'image est mongo version 6
    # rep : 
    container_name: mongo-db
    # Ajouter la ou les lignes : Expose MongoDB au host. Le port d'entrée et de sortie est 27017
    # rep : 
    volumes:
      - mongo-data:/data/db  # Persistance des données
    # Ajouter la ou les lignes : réseau utilisé, le nom du réseau est app-network
    # rep : 

  # -------------------------
  # Backend Node.js (API)
  # Utilise un Dockerfile
  # -------------------------
  backend:
    # Ajouter la ou les lignes : on utilise un Dockerfile créer plus haut qui se trouve dans le répertoire "./backend"
    # rep : 
    # Ajouter la ou les lignes : Le nom de ce conteneur doit être api-backend
    # rep : 
    # Ajouter la ou les lignes : Ajouter le # de port d'entrée et de sortie qui est le même. (L'information sur le # du port est dans le lab ;-P )
    # rep : 
    # Ajouter la ou les lignes : Ce conteneur dépend du conteneur database
    # rep : 
    # Ajouter la ou les lignes : réseau utilisé, le nom du réseau est app-network
    # rep : 


  # -------------------------
  # Frontend React
  # Utilise l'image Node
  # -------------------------
  frontend:
    image: node:18
    container_name: react-frontend
    # Ajouter la ou les lignes : le nome du répertoire de travail est "/app"
    # rep : 
    volumes:
      - ./frontend:/app     # Monte le code React
    ports:
      - "3000:3000"
    command: sh -c "npm install && npm start"  # Installe et lance le serveur de dev React
    # Ajouter la ou les lignes : réseau utilisé, le nom du réseau est app-network
    # rep : 

# -------------------------
# Volume persistant MongoDB
# -------------------------
volumes:
  mongo-data:

# -------------------------
# Réseau utilisé par les services
# -------------------------
networks:
  app-network:

Partie 4 — Démarrer l’environnement

docker-compose up -d --build

Partie 5 — Injecter des données dans MongoDB

docker-compose exec backend npm run seed

Partie 6 — Vérifier et tester la solution

Vérifier que les conteneurs sont démarrés

docker-compose ps

Vérifier si les données sont dans le conteneur

Trouve la commande et montrez-moi les données exécutant ces commandes dans le conteneur.

On te donne les lignes nécessaires pour afficher les données, trouve le bout manquant qui se trouve entre crochets

[Entre la commande docker] mongosh

Une fois dans le conteneur, faites ces commandes.

use cours
db.etudiants.find()

# pour sortir de mongodb et retrouver la console, faites "exit"

Faites une capture d’écran et enregistrez-la.

Montrer que le serveur Rest Api fonctionne sur le host

curl http://localhost:5000/
curl http://localhost:5000/etudiants

Faites une capture d’écran et enregistrez-la.

Partie 7 — Vérifier et tester la solution finale sur le host

Dans Chrome testez : http://localhost:3000 ou http://ip-vm:3000 à partir d’une autre vm

Faites une capture d’écran et enregistrez-la.


Questions à remettre dans votre journal

  1. Expliquez comment les services communiquent entre eux dans Docker Compose.
  2. Comment pourrait-on sécuriser l’architecture et faire en sorte que la machine hôte puisse accéder seulement au conteneur frontend (http://localhost:3000).
  3. Qu’elle est la différence entre image: et build: dans Docker Compose ?
  4. Mettre les captures d’écrans demandées plus haut

Grille d’évaluation

Section Points
1. Structure du projet 6 pts
2. Dockerfile 3 point par ligne 12 pts
3. docker-compose.yaml Entre 1 et 3 points par ligne 32 pts
4. Questions de compréhension 14 pts
Total 64 pts

Toute autre ligne superflue : -1 pt pour le Docker Compose et -2 points pour le Dockerfile


3. docker-compose.yaml (détail)

Critère Points
3.1 Service database correct 7 pts
3.2 Service backend correct 11 pts
3.3 Service frontend correct 8 pts
3.4 L’exécution du Docker compose fonctionne et les données sont présentes. 6 pts
Total 32 pts

4. Questions de compréhension et capture d’écran (détail)

Critère Points
4.1 Comment pourrait-on sécuriser l’architecture et faire en sorte que la machine hôte puisse accéder seulement au conteneur frontend (http://localhost:3000). 2 pts
4.2 Différence entre image: et build: 3 pts
4.3 Captures d’écran demandées 7 pts
Total 14 pts