Construire des images Docker Java prêtes pour l’orchestration
2026-09-30
Comment transformer une application Java en image Docker exploitable en production.
À l’issue, vous devez comprendre :
Important
Ce chapitre ne vise pas à maîtriser toutes les techniques, mais à comprendre les trajectoires possibles.
Les exemples suivants sont accessibles dans le dépôt :
✅ : ebpro/notebook-containers-intro-sample-java-helloworld
/home/jovyan/work/examples/github/ebpro/notebook-containers-intro-sample-java-helloworldClone Command:
La méthode la plus directe consiste à utiliser une image Maven officielle. C’est l’approche “tout-en-un” où l’on compile et exécute au même endroit.
Dockerfile.10.maven
Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0
07:04:08.564 INFO fr.univtln.bruno.demos.docker.App - Java Vendor: Eclipse Adoptium | Version: 25.0.4.1
07:04:08.572 INFO fr.univtln.bruno.demos.docker.App - Démarrage de l'application (Iterations: 10000)...
07:04:08.655 INFO fr.univtln.bruno.demos.docker.App - Traitement terminé. Éléments filtrés : 8926 | Temps : 82 ms
Fin du programme. (Éléments traités: 8926)
ANALYSE DE L'IMAGE : javahello:mavenimage • Sécurité : ✅ appuser • Surface : ⚠️ Shell présent • Structure : ❌ Polluants (Maven ou /src) • Runtime : ☕ Standard (JRE) • Java Opts : ❌ Manquante • Poids : 509MB
Analyse critique
Le Multi-stage build est la stratégie de référence. On utilise une image “lourde” pour compiler, puis on ne transfère que le .jar et les dépendances (lib/*.jar) vers une image JRE légère pour l’exécution.
Dockerfile.20.stage
ANALYSE DE L'IMAGE : javahello:mavenimagestage • Sécurité : ✅ appuser • Surface : ⚠️ Shell présent • Structure : ✅ Artefact pur (Multi-stage OK) • Runtime : ☕ Standard (JRE) • Java Opts : ❌ Manquante • Poids : 298MB
Pour être orchestrée (Kubernetes, Compose), une image doit respecter des règles d’hygiène :
appuser. Cela empêche une faille applicative de compromettre l’hôte.ENTRYPOINT ["/script.sh"] permet à la JVM de recevoir le SIGTERM pour un arrêt propre.-XX:MaxRAMPercentage permet à la JVM d’être “Container Aware”.Docker permet de monter des caches persistants pour le répertoire ~/.m2. Cela évite de retélécharger les dépendances à chaque modification du code source.
Dockerfile.30.cache
ANALYSE DE L'IMAGE : javahello:dockercache • Sécurité : ✅ appuser • Surface : ⚠️ Shell présent • Structure : ✅ Artefact pur (Multi-stage OK) • Runtime : ☕ Standard (JRE) • Java Opts : ❌ Manquante • Poids : 298MB
Note
L’instruction --mount=type=cache,target=/root/.m2 est une fonctionnalité BuildKit qui transforme radicalement l’expérience de CI/CD.
L’usage de SDKMAN permet un contrôle granulaire sur les versions exactes du JDK et des outils de build, indépendamment des images Maven officielles.
Dockerfile.40.manual
ANALYSE DE L'IMAGE : javahello:manual • Sécurité : ✅ appuser • Surface : ⚠️ Shell présent • Structure : ✅ Artefact pur (Multi-stage OK) • Runtime : ☕ Standard (JRE) • Java Opts : ❌ Manquante • Poids : 298MB
jlink permet de créer un runtime Java sur mesure contenant uniquement les modules nécessaires.
Avertissement
Nécessite une application modularisée (JPMS) et une analyse fine des dépendances.
Dockerfile.50.jlink
ANALYSE DE L'IMAGE : javahello:jlink • Sécurité : ✅ appuser • Surface : ⚠️ Shell présent • Structure : ✅ Artefact pur (Multi-stage OK) • Runtime : ☕ Standard (JRE) • Java Opts : ❌ Manquante • Poids : 121MB
jlink-alpine propose un runtime Java construit sur Alpine (musl) contenant uniquement les modules nécessaires. C’est une excellente option pédagogique pour montrer l’impact du runtime sur la taille d’image, mais elle comporte des limites pratiques.
Avertissement
Alpine utilise musl (libc alternative). Les composants natifs (JNI), certaines bibliothèques précompilées ou des outils attendus par glibc peuvent ne pas fonctionner. Testez systématiquement avant production.
Avantages:
Inconvénients:
Commandes utiles (exemples étudiants) :
Recommandation : pour un déploiement robuste, préférez jlink (Debian/distroless) sauf si vous maîtrisez l’ensemble des dépendances natives.
GraalVM compile Java en binaire natif.
Dockerfile.60.graalvm
ANALYSE DE L'IMAGE : javahello:graalvm • Sécurité : ✅ nonroot:nonroot • Surface : ✅ Minimaliste / Distroless • Structure : ✅ Artefact pur (Multi-stage OK) • Runtime : 🚀 Natif (GraalVM app) • Java Opts : ✅ N/A (Binaire natif) • Poids : 20MB
| Image Tag | Build Cold | Size | Peak RAM | Surface d’Attaque |
|---|---|---|---|---|
| mavenimage | 28s | 928MB | 86.01 MiB | Maximale |
| mavenimagestage | 24s | 406MB | 71.97 MiB | Moyenne |
| jlink-alpine | 30s | 163MB | 55.83 MiB | Faible |
| graalvm | 57s | 46MB | 5.02 MiB | Minimale |
Points clés pour la mise en production
stdout/stderr (laissé à la charge de l’orchestrateur).Prochaine étape : orchestrer ces images avec Docker Compose.
E. Bruno - Conteneurs — Application à Java