KYOSH1RO

◀ Cheatsheets / DOCKER & CONTAINERS

Dockerfile — Bonnes pratiques de build

Écrire des Dockerfiles rapides, sûrs et légers : cache de layers, multi-stage builds, .dockerignore, utilisateur non-root, secrets BuildKit et réduction des images.

Filtrer
Un bon Dockerfile produit une image reproductible, minimale, rapide à reconstruire et simple à maintenir. L'ordre des instructions détermine l'efficacité du cache, tandis que le contenu de l'image définit sa surface d'attaque.

Choisir une image de base

4 cmds
● Utiliser une image officielle ou une source de confiance
● Choisir une variante adaptée au runtime, par exemple slim lorsque c'est pertinent
● Éviter latest pour garder un minimum de contrôle sur les changements
● Reconstruire régulièrement afin d'intégrer les correctifs de la base
● Évaluer les différences de compatibilité avant d'adopter Alpine
# syntax=docker/dockerfile:1
FROM node:22-bookworm-slim
docker build --pull -t mon-app:latest .Récupérer une base plus récente
docker build --pull --no-cache -t mon-app:latest .Refaire toutes les étapes
docker image inspect node:22-bookworm-slimInspecter la base locale
Un tag est mutable. Pour une reproductibilité stricte, il peut être complété par un digest, au prix d'une mise à jour volontaire du digest lors des correctifs.

Réduire le contexte avec .dockerignore

12 cmds
Le contexte de build est envoyé au builder. Exclure les fichiers inutiles accélère l'envoi, limite les invalidations du cache et évite d'inclure accidentellement des secrets.
.git
.gitignore
node_modules
npm-debug.log
.env
.env.*
coverage
dist
tmp*
Dockerfile*
compose*.yaml
docker build --progress=plain -t mon-app .Voir les étapes et le contexte
.dockerignore n'est pas un contrôle d'accès. Les secrets ne doivent pas vivre dans le dépôt ni être transmis au build s'ils ne sont pas nécessaires.

Optimiser le cache des layers

11 cmds
Docker réutilise une layer si l'instruction et les fichiers dont elle dépend n'ont pas changé. Copier les manifests de dépendances avant le reste du code évite de réinstaller toutes les dépendances à chaque modification.
Ordre inefficace
FROM node:22-bookworm-slim
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build
Ordre optimisé
FROM node:22-bookworm-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

Utiliser les cache mounts BuildKit

8 cmds
# syntax=docker/dockerfile:1
FROM node:22-bookworm-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY . .
RUN npm run build
docker buildx build --progress=plain -t mon-app .
docker buildx pruneNettoyer le cache après confirmation

Multi-stage build

18 cmds
Un build multi-stage sépare les outils de compilation du runtime. Seuls les artefacts nécessaires sont copiés dans l'image finale.
# syntax=docker/dockerfile:1
FROM node:22-bookworm-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY . .
RUN npm run build && npm prune --omit=dev
FROM node:22-bookworm-slim AS runtime
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build --chown=node:node /app/package.json ./package.json
COPY --from=build --chown=node:node /app/node_modules ./node_modules
COPY --from=build --chown=node:node /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]
docker build --target build -t mon-app:build .S'arrêter au stage build
docker build -t mon-app:latest .Construire le stage final
docker images mon-appComparer les tailles

Installer les paquets proprement

5 cmds
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/*
● Combiner apt-get update et apt-get install dans la même instruction
● Utiliser --no-install-recommends lorsque les recommandations sont inutiles
● Supprimer les index APT dans la même layer
● Ne pas installer éditeur, compilateur ou outils de debug dans l'image de runtime

COPY, ADD et propriété des fichiers

2 cmds
COPY --chown=app:app ./src /app/src
COPY --from=build --chown=app:app /build/app /usr/local/bin/app
Préférer COPY pour les fichiers du contexte. Utiliser ADD uniquement lorsque ses fonctions spécifiques, comme une ressource distante avec checksum, sont réellement nécessaires.

Exécuter sans root

8 cmds
FROM debian:bookworm-slim
RUN groupadd --system app && useradd --system --gid app --create-home app
WORKDIR /app
COPY --chown=app:app . .
USER app
CMD ["./mon-app"]
docker run --rm mon-app idVérifier l'identité dans le conteneur
docker inspect -f '{{.Config.User}}' mon-appVoir l'utilisateur déclaré
L'utilisateur non-root réduit l'impact d'une compromission, mais ne remplace pas les autres protections : capabilities minimales, système de fichiers en lecture seule et secrets externes.

Ne pas stocker les secrets dans les layers

5 cmds
À éviter
ARG TOKEN
ENV TOKEN=$TOKEN
RUN curl -H "Authorization: Bearer $TOKEN" https://exemple/prive
Secret BuildKit
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
docker build --secret id=npmrc,src=.npmrc -t mon-app .
Les valeurs ARG et ENV ne conviennent pas aux secrets de build : elles peuvent apparaître dans l'historique, les métadonnées ou les layers. Utiliser les secrets BuildKit et fournir les secrets d'exécution au démarrage.

CMD, ENTRYPOINT et signaux

4 cmds
ENTRYPOINT ["/usr/local/bin/mon-app"]
CMD ["--listen", "0.0.0.0:8080"]
● Préférer la forme JSON exec pour éviter un shell intermédiaire
● Le processus principal doit rester au premier plan
● L'application doit gérer SIGTERM pour s'arrêter proprement
● Éviter les scripts shell qui oublient exec devant le processus final
Script d'entrée correct
#!/bin/sh
set -e
exec "$@"

HEALTHCHECK

4 cmds
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD wget -qO- http://127.0.0.1:3000/health || exit 1
docker inspect -f '{{json .State.Health}}' conteneurVoir l'historique du healthcheck
docker psÉtat healthy ou unhealthy
Le programme utilisé par le healthcheck doit réellement être présent dans l'image. Un test trop coûteux ou dépendant d'un service externe peut créer de faux négatifs.

Build reproductible et métadonnées

6 cmds
LABEL org.opencontainers.image.title="mon-app" \
org.opencontainers.image.source="https://github.com/exemple/mon-app" \
org.opencontainers.image.version="1.4.0"
docker build --build-arg VERSION=1.4.0 -t mon-app:1.4.0 .
docker image inspect mon-app:1.4.0
docker history --no-trunc mon-app:1.4.0

Mesurer et analyser l'image

5 cmds
docker images mon-appTaille des tags locaux
docker history mon-app:latestTaille de chaque layer
docker image inspect mon-app:latest --format '{{.Size}}'Taille en octets
docker scout quickview mon-app:latestVue sécurité si Docker Scout est disponible
docker scout cves mon-app:latestVulnérabilités connues

Checklist finale

● Une image de base maintenue et versionnée est utilisée
● Le contexte est réduit avec .dockerignore
● Les manifests de dépendances sont copiés avant le code
● Les outils de build restent dans un stage intermédiaire
● Les paquets et caches inutiles sont retirés
● Le runtime s'exécute avec un utilisateur non-root
● Aucun secret n'est passé par ARG, ENV ou COPY
● CMD ou ENTRYPOINT utilise la forme exec
● L'image est reconstruite et analysée régulièrement
● Le conteneur peut être supprimé et recréé sans perdre ses données

Aucune commande ne correspond à ce filtre.