Pourquoi l’ordre du Dockerfile change-t-il le cache ?

Questions d’entrevue Docker

Intermédiaireimagescouchescache

La réponse courte

Chaque instruction du Dockerfile (FROM, RUN, COPY, …) produit une couche. Au build suivant, Docker compare l’instruction et ses entrées à ce qu’il a déjà : si rien n’a changé, il réutilise la couche ; si quelque chose a changé, il invalide cette couche et toutes celles d’après.

L’ordre n’est donc pas une affaire de style. Il décide ce qui est recalculé à chaque commit.

dockerfile
# Les dépendances bougent rarement : on les copie d’abord.
COPY package.json package-lock.json ./
RUN npm ci

# Le code bouge à chaque commit : on le copie ensuite.
COPY src ./src

Si vous inversez — COPY . . puis RUN npm cichaque modification d’un fichier source casse le cache de l’installation. Vous retéléchargez internet pour avoir changé une virgule.

Ce que l’intervieweur vérifie

Que vous connaissez la règle d’invalidation, pas seulement « le cache accélère le build ». La phrase attendue : la première instruction dont l’entrée change jette le reste.

Deux précisions qui séparent une réponse moyenne d’une bonne :

  1. COPY et ADD hashent le contenu. Ce n’est pas le texte de la ligne qui compte, c’est le fichier. Un COPY src ./src est un miss dès qu’un fichier de src/ change, même si la ligne du Dockerfile est identique.
  2. Un RUN trop large (apt-get update && npm ci && npm run build dans la même couche) est un cache tout-ou-rien. Parfois c’est voulu (nettoyer les listes apt dans la même couche) ; parfois vous avez collé deux cycles de vie différents.

La relance probable

« Pourquoi mon cache est-il mort alors que je n’ai touché que le README ? »

Parce qu’un COPY . . trop tôt a vu le README. C’est le cas d’école du fichier dockerignore oublié.

« Le cache peut-il être trop agressif ? »

Oui. Une couche RUN npm ci réutilisée alors que le registre a publié un correctif, ou un ARG oublié qui ne fait pas partie de la clé. Le cache n’est pas un oracle : il répète ce qu’il a déjà fait. Le diagnostic de ce cas est une question à part.

Toutes les questions Docker