On ne vous demande pas un chef-d’œuvre. On vous demande un fichier qu’un inconnu peut reconstruire dans six mois et qu’on oserait pousser. Sur un tableau, j’écris ceci et je justifie chaque ligne :
# syntax=docker/dockerfile:1
FROM eclipse-temurin:21-jdk AS builder
WORKDIR /src
COPY pom.xml .
RUN --mount=type=cache,target=/root/.m2 mvn -B -DskipTests dependency:go-offline
COPY src ./src
RUN --mount=type=cache,target=/root/.m2 mvn -B -DskipTests package
FROM eclipse-temurin:21-jre
WORKDIR /app
RUN useradd --system --uid 10001 app
COPY --from=builder --chown=app:app /src/target/app.jar ./app.jar
USER 10001
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]Autour, pas dans le fichier : un .dockerignore, un tag autre que latest, le digest en déploiement, des tests avant le build dans la CI.
Ce que ce squelette dit, dans l’ordre du recruteur :
ubuntu:latest.USER numérique, pas root.ADD magique, pas de vim pour debug.HEALTHCHECK si le runtime est Docker/Compose et que personne d’autre ne sonde. Labels OCI si on vous demande la traçabilité. Distroless si le debug est déjà prévu ailleurs.
Moins la syntaxe que ce que vous refusez d’écrire. COPY . . en première ligne, npm install sans lock, curl | bash dans un RUN, un mot de passe en ENV, USER root « le temps que ça marche », un latest. Chaque refus est une question que vous avez déjà traitée dans cette série.
Il écoute aussi le périmètre. Un Dockerfile propre ne configure pas le cluster. Il produit un colis. Les replicas, les probes, le Service : Kubernetes prend la suite. Mélanger les deux sur le tableau est un signal de confusion, pas de séniorité.
Le cas Java développé, avec les ordres de grandeur de taille, est dans alléger une image Docker Java.
« Où mettez-vous la version de l’appli ? »
Un ARG recopié en LABEL ou en ENV non secret, fourni par la CI. Pas un chiffre écrit à la main et oublié.
« Pourquoi pas Alpine partout ? »
Parce que musl n’est pas un trophée. JRE glibc slim + multi-étapes bat souvent Alpine+JDK, et casse moins de binaires natifs. On choisit la base pour le runtime, pas pour le tweet de taille.