Leçons 1/4 · 15 min
Une image reproductible et versionnée
Pourquoi « ça marche chez moi » ne suffit pas
Amina a un nœud de test qui tourne sur son portable. Brice, son collègue, le lance à son tour : il plante, car sa machine a une autre version d'une bibliothèque. Personne n'a mal travaillé : le programme dépendait de choses que personne n'avait écrites.
Trois mots d'abord.
- Un conteneur est un programme lancé comme un processus isolé : il voit ses propres fichiers, ses propres bibliothèques et sa propre vue du réseau. Contrairement à une machine virtuelle, il partage le noyau Linux de la machine hôte (sous Windows ou macOS, Docker Desktop fait tourner une petite machine virtuelle Linux entre les deux, mais la logique reste la même).
- Une image est le paquet en lecture seule à partir duquel on démarre des conteneurs. Une image est à un conteneur ce qu'un fichier de programme est à un programme en cours d'exécution.
- Un Dockerfile est la recette écrite qui fabrique une image.
Lire un Dockerfile
Exemple pour un petit service Node.js (l'indexeur de l'atelier). Les valeurs entre chevrons sont à remplacer par vous-même.
FROM node:<tag>@sha256:<empreinte-relevée>
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
USER node
CMD ["node", "index.js"]Chaque instruction est une étape. Celles qui modifient les fichiers (COPY, RUN) produisent une couche mise en cache : si rien n'a changé depuis la dernière construction, Docker la réutilise (« CACHED » dans la sortie). Dès qu'une étape change, toutes les suivantes sont refaites. Remarque : ici COPY . . s'exécute avant USER node, donc les fichiers de /app appartiennent à root et sont seulement lisibles par node ; si l'application doit y écrire, utilisez COPY --chown=node:node . ..
Reproductible veut dire épinglé
Trois leviers, du plus important au moins visible.
- L'image de base.
FROM ubuntu:latestne promet rien :latestest juste le nom d'étiquette par défaut, celle que l'éditeur a déplacée en dernier. Une étiquette (tag) peut être déplacée ; une empreinte (@sha256:…) ne le peut pas, car c'est le hachage SHA-256 du manifeste de l'image : un contenu différent donne une empreinte différente, comme dans l'atelier sur les fonctions de hachage. On la relève avecdocker images --digestspour une image tirée d'un registre (une image construite localement n'en a pas tant qu'elle n'est pas poussée) ; sinon, sur la page du registre. Pour une image multi-architecture, l'empreinte qu'on épingle est en général celle de l'index, qui renvoie vers les variantes par architecture. - Les dépendances. Un fichier de verrouillage (
package-lock.json) fige les versions exactes ;npm ciles installe telles quelles et échoue si le fichier etpackage.jsondivergent.npm installpeut, lui, résoudre autrement. - Votre propre version. Étiquetez ce que vous construisez avec un numéro explicite, par exemple
bac-testnode:lab-1, jamais seulementlatest.
Ce cours n'écrit volontairement aucun numéro de version « actuel » : les versions changent. Vous apprenez à les épingler et à les vérifier (page de publication du projet, docker images --digests, npm ls), puis à noter ce que vous avez choisi.
L'ordre des instructions compte
Dans l'exemple, on copie d'abord les deux fichiers de dépendances, puis npm ci, puis le reste du code. Si vous modifiez index.js, seule la dernière copie est refaite : l'installation, longue, reste en cache. Si vous aviez écrit COPY . . avant RUN npm ci, chaque modification d'une ligne de code relancerait l'installation complète. Ajoutez aussi un fichier .dockerignore pour exclure .git, node_modules et surtout .env du contexte envoyé à la construction.
Ce que cela ne garantit PAS
- Pas des octets identiques : une construction peut embarquer des dates, ou un
apt-get updatequi récupère ce que le miroir contient aujourd'hui. « Reproductible » veut ici : même comportement avec les mêmes entrées épinglées. - Épinglé ne veut pas dire sûr. Une empreinte fige aussi une faille connue : il faut mettre à jour volontairement, en changeant l'empreinte et en retestant.
- Une étiquette qui marche aujourd'hui peut pointer ailleurs demain.
À retenir : image de base par empreinte, dépendances verrouillées, version explicite, cache bien ordonné.
