Pourquoi un secret dans le Dockerfile reste dans l’image ?

Questions d’entrevue Docker

Seniorsecuriteimagescouches

La réponse courte

Parce qu’une image n’est pas un disque qu’on nettoie. C’est une pile de diffs. Une couche qui a vu le secret le garde, même si la couche suivante fait rm. docker history, un docker save, ou un registre mal configuré suffisent à le relire.

Les formes classiques du piège :

dockerfile
# Visible dans l’historique et souvent dans l’image finale.
ENV DATABASE_PASSWORD=hunter2
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc && npm ci
COPY id_rsa /root/.ssh/id_rsa

ENV est inspectable. ARG apparaît dans l’historique du build. Un COPY de clé, même suivi d’un RUN rm, laisse la clé dans la couche du COPY. Un multi-étapes n’efface rien si vous copiez le secret dans l’étape finale, ou si vous poussez aussi l’étape builder.

Ce que l’intervieweur vérifie

Que vous avez compris l’immuabilité des couches, pas seulement « on ne met pas de mot de passe dans Git ». La question vise le candidat qui a déjà fait docker history après un incident.

La réponse senior nomme le remède BuildKit, pas un rm plus énergique :

dockerfile
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci

Le secret est monté le temps du RUN, il n’entre pas dans la couche. En CI : docker build --secret id=npm,env=NPM_TOKEN. Pour un fichier d’identifiants cloud, le même motif. Pour le runtime : un gestionnaire de secrets (injecté en variable ou en fichier temporaire), jamais un ENV cuit.

Ce qui ne compte pas comme réponse : « on est en privé, le registre est interne ». Un registre interne a des lecteurs, des backups, des copies locales sur les laptops. Le secret dans une couche est un secret distribué.

La relance probable

« Et un .env copié puis retiré dans la même instruction RUN ? »

Mieux que deux couches, encore faux si le .env vient d’un COPY précédent. Le montage secret, ou l’absence totale de ce fichier dans le contexte — dockerignore — est la voie propre.

« Comment vous vérifiez qu’une image déjà poussée est propre ? »

docker history --no-trunc, scan des chaînes, et on retires le tag. On ne « patche » pas une couche. On reconstruit depuis un Dockerfile qui n’a jamais vu le secret, on invalide les tags, on fait tourner les credentials.

Toutes les questions Docker