TW3 — Technologies du Web 3

Exercice — Conteneuriser une app Node.js

Conteneurisez une app Node.js avec un Dockerfile multi-étapes, un docker-compose.yml et une base MongoDB persistante.

Objectif : prendre une app Node existante et la conteneuriser — Dockerfile multi-étapes, docker-compose.yml avec MongoDB, volume de persistance et exposition du port. Vous pratiquez images, conteneurs, réseau et stockage.

Le projet : une app dans un conteneur

Partons d'un server.js Express (port 3000). Écrivez un Dockerfile multi-étapes, puis un docker-compose.yml qui lance l'application et une base MongoDB sur le même réseau Docker.

Étapes pas à pas

1. Le Dockerfile

Partir de node:20-alpine, créer un stage build, installer les dépendances, puis copier uniquement le nécessaire dans un stage final plus léger. Exposer 3000.

2. Le fichier docker-compose.yml

Déclarer deux services :

  • api : build local de votre image Node.js
  • mongo : image mongo:7 avec un volume nommé pour persister les données

3. Lancer l'ensemble

docker compose up --build

4. Vérifier

docker ps, docker compose logs api puis curl localhost:3000.

Le projet complet

FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm prune --omit=dev

FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/package*.json ./
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/server.js ./server.js
EXPOSE 3000
CMD ["node", "server.js"]
services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      PORT: 3000
      MONGODB_URI: mongodb://mongo:27017/monapp
    depends_on:
      - mongo

  mongo:
    image: mongo:7
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_DATABASE: monapp
    volumes:
      - mongo-data:/data/db

volumes:
  mongo-data:
docker compose up --build -d
docker compose ps
docker compose logs api
curl http://localhost:3000

L'application doit lire process.env.MONGODB_URI pour se connecter à MongoDB. Dans le compose, le nom d'hôte mongo correspond directement au nom du service.

Conseils

  • Utilisez node:20-alpine (léger) plutôt qu'une image complète.
  • npm ci est reproductible (utilise package-lock.json).
  • Un .dockerignore évite de copier node_modules/.git inutiles.
  • Le volume mongo-data conserve les données MongoDB même si vous recréez les conteneurs.

⚠️ Pièges à éviter

Données perdues sans volume : tout ce qui est écrit dans le conteneur disparaît à sa suppression. Montez un volume sur MongoDB pour la persistance.

Port non mappé : le mapping 3000:3000 dans ports: est indispensable pour rejoindre l'application depuis l'hôte ; sinon elle reste isolée dans le réseau Docker.

COPY . . avant npm install : invalide le cache de build à chaque modification de code. Copiez d'abord package*.json.

Image qui tourne en root : pour la prod, créez un utilisateur non-root (USER node) afin de limiter l'impact d'une compromission.

Critères de réussite

  • Dockerfile multi-étapes basé sur une image officielle, avec WORKDIR et EXPOSE.
  • docker-compose.yml avec les services api et mongo.
  • Volume nommé pour la persistance MongoDB.
  • App accessible via localhost:3000.

Pour aller plus loin

Relisez Introduction à Docker et Création d'image avant le quiz.

Docker

Terminez le quiz du chapitre pour le marquer comme complété.

Tableau de bord

On this page