Maximize Page
Tech & DevOps HubEspace Tech & DevOps: Explorez le monde du Dev, du Cloud et des outils DevOps à travers nos articles et discussions Explore the world of development, the cloud and DevOps tools

Optimisation du Dockerfile et Dockerfile.debug

Date de l'article:01-01-2026
Docker CI/CD Github-Actions
On remplace l'image de base et observons la possibilité d'un Dockerfile.debug en parallèle. Nous ferons la comparaison des approches et verrons comment, le positionnement d'Actuator peut devenir une alternative au debug via container

Avant de décider quoi que ce soit, il faut se renseigner, savoir pourquoi et dans quel cas on le ferait;
Les objectifs seront: de réduire la surface d'attaque, forcer l'exécution en utilisateur non-root, et ne conserver que le runtime Java nécessaire


Comparatifs technique
Options temurin:17-jre-alpine distroless/java17
Shell disponible Oui (sh) Non
Package manager Oui (apk) Non
Utilisateur root Oui par défaut Nonroot fourni
Surface d'attaque Moyenne Minimale
Debug facile Oui Non
Usage recommandé Dev / Debug Production
Points importants pour l'image "distroless"
L'image ne contient aucun outil inutile (shell, gestionnaire de paquets)
→ On ne peut pas “entrer” dans le conteneur avec une commande "sh"
L'utilisation d'un USER nonroot utilise le principe du moindre privilège, conforme aux standards sécurité cloud
→ Distroless fournit cet utilisateur
L'image java17-debian12, basée sur Debian 12 (glibc)
Garantit la compatibilité avec: PostgreSQL, Oracle, drivers JDBC natifs et
les librairies natives éventuelles

Modification de l'image Docker

Dans le premier pipeline , nous utilisions l'image JRE Alpine. Et, bien que cette image soit déjà bien optimisée, légère et avec de bonne performance;
Pour un environnement de production, on peut aller plus loin, en matière de sécurité et de réduction de surface d'attaque

Ancienne image utilisée: JRE Alpine
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/flashcards-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
update 05/05/26: L'image debian12 représentant trop de Vulnérabilités, je l'ai modifiée en debian13:nonroot
Modifiée, comme ceci:
FROM gcr.io/distroless/java17-debian12
WORKDIR /app
COPY target/flashcards-*.jar app.jar

USER nonroot
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Dockerfile et Dokerfile.debug

Au vue du comparatif, sachant qu'elle impose des restrictions, vient alors tout naturellement l'idée d'utiliser un Dockerfile.debug

Pourquoi utiliser une image debug?
Une image distroless ne permets pas:
D'avoir un shell, impossible de faire: docker exec -it container sh
L'installation d'outils
L'inspection simple des fichiers
Des commandes ping - curl - wget
D'analyse rapide du réseau
En quoi consiste le Dockerfile.debug ?
L'idée est simple: Avoir deux images différentes, pour deux usages différents:
Image Objectif
Dockerfile Production sécurisée
Dockerfile.debug Développement / Investigation

Cela change la culture d'investigation.
Lors d'incident en production, cela peut compliquer l'analyse


Exemple de Dockerfile "debug" en parallèle
# Dockerfile.debug
FROM eclipse-temurin:17-jre-slim

WORKDIR /app
COPY target/flashcards-*.jar app.jar

RUN useradd -m appuser && chown -R appuser /app
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

On peut alors construire et taguer différemment:
# prod (distroless):
docker build -f Dockerfile -t val7304/flashcards:prod .
# debug:
docker build -f Dockerfile.debug -t appuser/flashcards:debug .

Cela permet d'avoir: en Prod: Une image légère et sécurisée (distroless)
en local (debug/incident): L'image avec shell et outils installables (temurin-slim)

Quand créer/garder un Dockerfile.debug ?
→ Si l'équipe est large, l'infra complexe, ou que l'on utilise Kubernetes.
→ Si on a fréquemment besoin de troubleshooting "bas niveau" ou, si l'on ne dispose pas encore de système d'observabilité mature

D'un point de vue DevOps
Dans un environnement bien conçu, on n'entre pas dans le container
      On utilise:
→ Les logs centralisés
→ Les metrics Prometheus et les Dashboards Grafana, l'alerting
→ Actuator
APM (si présent)

L'accès au shell devient un anti-pattern.
     Et c'est précisément l'argument fort pour utiliser une image distroless

L'utilisation de distroless n'est pas un simple choix esthétique, c'est aussi une décision de sécurité et une discipline d'immutabilité

Cas réels où on entre dans un container
Idéalement on ne le fait pas, mais dans la réalité: Il existe des cas réels où cela arrive
Incident critique inexpliqué:
L'application ne répond plus, le CPU est à 100%, les sont threads bloqués
On peut vouloir: Inspecter/Vérifier des fichiers ou la config, analyser un dump
Problème réseau complexe
DNS mal résolu, connexion DB instable, problème de proxy
On peut vouloir: tester les commandes ping, curl, nslookup, netstat
! Mais Pas dans une image prod hardened
Fuite mémoire avancée:
On peut vouloir: Générer un heap dump, l'extraire et l'analyser

Actuator, l'alternative au Docker debug

A ce stade, comme nous avons déja configuré Actuator et la classe Sécurité, nous pouvons simplement ajouter les nouveaux indicateurs à la suite, dans le fichier de configuration du profil

Ajout de 2 indicateurs dans l'application Flashcards

En dev, nous avions déjà activé:
health, info, metrics, mappings, env, configprops, loggers

En staging: ajoutez: heapdump en fin de liste

En staging / prod:
Ajoutez management.endpoint.env.show-values=never
pour éviter la fuite de secrets

En prod: , ajoutez: threaddump en fin de liste

threaddump
Cas d'usage :
Application bloquée, threads WAITING/BLOCKED, deadlock, pool saturé, problème Tomcat
Impact sécurité : faible

heapdump
Plus sensible, il permet:
Un bump mémoire complet, une analyse fuite mémoire, un diagnostic
Mais: Le fichier est lourd et peut contenir données sensibles qui pourrait avoir un impact momentané sur les performances

Recommandations & Améliorations possibles
Ajouter un health check dans le Dockerfile.debug

Est une bonne pratique complémentaire (sur une image non-distroless) et, peut être une alternative à un Healthcheck géré par un orchestrateur (Docker Compose /Kubernetes)
ou, à un monitoring externe

HEALTHCHECK --interval=30s --timeout=5s --start-period=30s CMD \
  wget -qO- http://localhost:8080/actuator/health || exit 1
Le fichier ".dockerignore" doit toujours exclure, a minima:
.git
.gitignore
target/
node_modules/
README.md  

Les builds seront plus rapides Le contexte Docker réduit
Une meilleure performance CI dans GitHub Actions


Conclusion pour le projet Flashcards
Pour un projet simple:
Le Dockerfile distroless est un choix production solide et moderne
Le Dockerfile.debug est utile mais pas obligatoire
Dans un petit service, Actuator remplace largement l'accès shell
Pour mon cas (petit service Spring Boot, Docker Hub, GitHub Actions)
Garder distroless pour la prod
→   Eventuellement, ajouter un Dockerfile.debug pour avoir
      accès au shell dans le container

Point important
     La mise à jour de certaines actions CI/CD (dependabot) sont succeptible d'engendrer des modifications dans les workflows, images et/ou le code,
     Le repository constitue dès lors, La source de vérité
Dans l'article suivant, nous créerons et automatiserons la promotion entre les branches [develop] et [staging] et ensuite de [staging] vers la production [main]

Laissez-moi un commentaire

En postant un commentaire anonyme, vous adhérez automatiquement aux conditions d'utilisation du site.