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.jsmongo: imagemongo:7avec 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:3000L'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 ciest reproductible (utilisepackage-lock.json).- Un
.dockerignoreévite de copiernode_modules/.gitinutiles. - Le volume
mongo-dataconserve 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
WORKDIRetEXPOSE. -
docker-compose.ymlavec les servicesapietmongo. - 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é.
🗃️ Cas Pratique : Stockage Docker
Dans ce cas pratique, nous allons explorer comment Docker gère le stockage persistant en utilisant deux techniques courantes : les volumes Docker et les bind mounts.
🧾 TLDR Docker
Docker empaquette une application avec toutes ses dépendances dans un conteneur léger, garantissant qu'elle s'exécute de façon identique sur n'importe quel environnement.