Exercice : Node.js en local vs Node.js dans Docker
Informations générales
Élément |
Description |
|---|---|
Compétences |
Concevoir, conteneuriser et documenter un service applicatif en distinguant clairement exécution locale et en conteneur. |
Objectifs |
À la fin de cette séquence, vous saurez : (1) exécuter la même appli Node.js en local et dans Docker, (2) expliquer les différences d’environnement (réseau, FS, variables, versions), (3) choisir le mode adapté (dev vs prod). |
Durée estimée |
45–60 min |
Répertoire de travail |
|
Fichiers sources |
|
À produire |
Un document (PDF ou papier) avec vos réponses + captures (commandes, sorties), et les fichiers |
Moyens d’aide |
Le support de cours |
Pré-requis |
Node.js installé en local (n’importe quelle LTS), Docker Desktop ou Docker Engine. |
Partie A — Exécution locale (sans Docker)
Installez les dépendances puis lancez l’appli :
npm ci # ou npm install si pas de package-lock.json npm run start
Relevez :
Version de Node locale :
node -v→__________Port d’écoute (attendu: 3000) :
__________Répertoire courant (
process.cwd()affiché par l’appli) :__________
Modifiez une ligne dans
server.js. L’application se met-elle à jour sans relance ? Expliquez :Réponse synthétique (1–2 phrases) :
Test réseau :
Depuis le poste :
curl http://localhost:3000→ OK ?OUI/NONDepuis une autre machine du LAN :
http://<IP-poste>:3000→ OK ?OUI/NON(si NON, expliquez pourquoi).
Partie B — Conteneurisation (Docker)
B1. Dockerfile de base (prod simple)
Créez un Dockerfile (Node 22 Alpine) :
# syntax=docker/dockerfile:1
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm","run","start"]
Ajoutez un .dockerignore minimal :
node_modules
npm-debug.log
Dockerfile
.dockerignore
B2. Build & run
Construisez et taguez l’image :
docker build -t node-vs-docker:1.0 .
Démarrez le conteneur (nom:
app1) et publiez le port :docker run -d --name app1 -p 3000:3000 node-vs-docker:1.0
Vérifications (à noter dans le rendu) :
Accès depuis l’hôte :
curl http://localhost:3000→OUI/NONVersion de Node dans le conteneur :
docker exec app1 node -v # → ________
Répertoire courant vu par l’app (
/appattendu) :__________
B3. Différences observées (local vs Docker)
Complétez le tableau :
Aspect |
Local |
Docker |
Différence / Explication (1–2 phrases) |
|---|---|---|---|
Version de Node |
|||
Hot reload après édition |
|||
Chemin de travail |
|||
Port d’accès depuis autre machine |
|||
Accès au FS hôte |
|||
Variables d’environnement |
Partie C — Mode développement Docker (montage de volume)
Objectif : observer le hot reload et la séparation code/image.
Relancez en montant le code local dans le conteneur :
docker rm -f app1 docker run -d --name app1 -p 3000:3000 -v "$PWD":/app -w /app node:22-alpine sh -c "npm ci && npm run start"
Modifiez
server.jset rechargez la page.Les changements sont-ils visibles sans rebuild de l’image ?
OUI/NONExpliquez ce qui se passe (bind mount, couche RW) :
Réponse :
(Optionnel) Utilisez
nodemonpour un vrai hot reload :npm i -D nodemon
Adaptez
package.json("start": "nodemon server.js"). Testez.
Partie D — Réseau : hôte ↔ conteneur
Depuis le conteneur, testez l’hôte :
Windows/Mac :
ping host.docker.internal→ OK ?OUI/NONLinux : utilisez l’IP de la passerelle Docker (ex.
172.17.0.1) → OK ?OUI/NON
Depuis une autre machine du LAN, testez
http://<IP-hôte>:3000quand l’app est :(a) locale →
OK ?(b) dans Docker →
OK ?
Si non, identifiez le blocage (pare-feu, NAT, publication de port).
Partie E — Variables d’environnement et configuration
Lancez l’image avec une variable :
docker run -d --name app2 -p 3001:3000 -e APP_ENV=production node-vs-docker:1.0
Affichez
process.env.APP_ENVcôté serveur (log) et copiez la sortie :Sortie :
Comparez avec
set APP_ENV=dev && npm run start(Windows) ouAPP_ENV=dev npm run start(Linux/Mac) en local.
Expliquez la différence de passage d’ENV (shell vs run args) :Réponse :
Partie F — Nettoyage et reproductibilité
Supprimez conteneurs/images :
docker rm -f app1 app2 docker rmi node-vs-docker:1.0
Expliquez en quoi
npm ci+package-lock.jsonaméliorent la reproductibilité entre local et Docker :Réponse :
Questions de synthèse (à rédiger)
Quand préférez-vous local plutôt que Docker en développement, et pourquoi ?
Qu’apporte Docker en production par rapport à un Node installé “à la main” sur un serveur ?
Donnez deux pièges fréquents observés dans cet exercice et comment les éviter.
(Bonus) Multi‑stage build + user non-root
# syntax=docker/dockerfile:1
FROM node:22-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:22-alpine AS runner
WORKDIR /app
COPY --from=deps /app/node_modules /app/node_modules
COPY . .
USER node
EXPOSE 3000
CMD ["npm","run","start"]
Questions :
Avantages de
USER node?Pourquoi séparer l’étape
deps?
Réponses :
- …