« Si l’image se construit et que le conteneur démarre, elle est bonne. »
« Ça marche » n’est pas « c’est prêt ». Une image de production doit être légère (rapide à transférer), sûre (pas root, surface d’attaque réduite) et reproductible (mêmes versions partout). On va transformer une image « qui marche » en image de production.
À la fin de ce module, tu sauras…
- Construire en plusieurs étapes (multi-stage) pour alléger l’image finale
- Faire tourner un conteneur sous un utilisateur non-root
- Figer les versions pour des builds reproductibles
- Réduire le contexte de build avec un .dockerignore
01Le problème : des images trop grosses
Mesurer le gaspillage
Imagine une image qui a besoin d’outils pour se construire mais pas pour tourner. Exemple : un site généré par un outil Node, servi ensuite par Nginx. Une version naïve embarque tout Node dans l’image finale.
Manipuledocker images | grep soria-webComprends outils de build ≠ besoins d’exécution
Compilateurs, gestionnaires de paquets, dépendances de développement : utiles pour fabriquer, inutiles pour servir. Les laisser dans l’image finale, c’est du poids mort et une surface d’attaque supplémentaire.
02Le build multi-stage
Construire dans une étape, ne garder que le résultat
Manipulecd ~/soria-web
cat > Dockerfile <<'EOF'
# --- étape 1 : build ---
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# --- étape 2 : image finale ---
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
EOF–from=build). Node n’existe pas dans l’image finale.Comprends le principe du multi-stage
Un Dockerfile peut contenir plusieurs FROM : chaque bloc est une étape. On construit dans une étape « lourde », puis on copie uniquement les artefacts dans une étape finale « légère ». Résultat : une image de production minuscule, sans les outils de build. (Adapte selon ton appli — un site statique pur n’a pas besoin de l’étape Node.)
03Ne pas tourner en root
Réduire les privilèges du conteneur
Vérifie sous quel utilisateur tourne un conteneur par défaut :
Manipuledocker run --rm debian whoamiObserverootRUN useradd -r -u 10001 appuser
USER appuserComprends pourquoi non-root, encore
Même principe de moindre privilège que pour les services Linux (Phase 1). Si un attaquant s’échappe de l’application, il ne doit hériter que de droits minimaux, pas de root. L’instruction USER fixe l’utilisateur qui exécute le conteneur. (Note : servir sur un port < 1024 exige root ; en conteneur on utilise un port haut, ex. 8080, et on publie.)
04Figer les versions & ignorer l’inutile
Reproductibilité et contexte propre
nginx:1.27-alpine, pas nginx:latest. Une version figée garantit que l’image sera identique dans six mois.Réduis aussi le contexte envoyé au build avec un .dockerignore :
cat > .dockerignore <<'EOF'
node_modules
.git
*.md
EOFComprends latest, le piège
latest n’est pas « la dernière version » figée : c’est une étiquette mouvante. Un build qui marche aujourd’hui peut casser demain si latest change. On fige donc les versions de base. Et .dockerignore évite d’envoyer node_modules, .git… au build : plus rapide, plus propre, plus sûr.
✓Ce que tu retiens
Une image de production est légère (multi-stage : on ne garde que les artefacts), sûre (USER non-root, moindre privilège), et reproductible (versions figées, pas de latest, .dockerignore). « Ça marche » devient « c’est prêt à déployer ».
Durcis l’image SORIA Web
À faire
- Réécris le Dockerfile de SORIA Web avec une base figée (ex.
nginx:1.27-alpine). - Ajoute un
.dockerignorepertinent. - Si ton appli a une étape de build, passe en multi-stage ; sinon, justifie pourquoi ce n’est pas nécessaire.
- Construis
soria-web:2.0et compare sa taille aux versions précédentes (docker images). - Explique en 3 lignes les trois qualités d’une image de production.
?Auto-évaluation
1. À quoi sert un build multi-stage ?
À construire dans une étape avec tous les outils, puis ne copier que les artefacts dans une image finale légère — sans les outils de build.
2. Pourquoi éviter le tag latest en production ?
C’est une étiquette mouvante : le build n’est pas reproductible. On fige une version précise pour garantir des images identiques dans le temps.
3. Pourquoi faire tourner le conteneur en non-root ?
Moindre privilège : en cas de compromission, l’attaquant n’hérite pas des droits root.