Docker et Kotlin : conteneurisation d'applications de niveau avancé
\n\nLa conteneurisation est devenue une partie intégrante du développement moderne, et Kotlin ne fait pas exception. Si vous maîtrisez déjà les Dockerfile de base et le lancement de simples fichiers JAR, il est temps de passer au niveau supérieur. Dans cet article, nous aborderons les techniques avancées de conteneurisation d'applications Kotlin : la construction multi-étapes (multi-stage builds), l'optimisation de la taille des images, la configuration pour les frameworks Ktor et Spring Boot, ainsi que le travail avec Docker Compose dans un environnement de production.
\n\n1. Construction multi-étapes d'applications Kotlin
\n\nL'un des principaux problèmes lors de la conteneurisation d'applications JVM est la taille de l'image finale. Une image OpenJDK standard peut peser plus de 400 Mo. La construction multi-étapes permet de séparer l'environnement de construction de l'environnement d'exécution, en utilisant une image runtime minimale.
\n\nExemple pour un projet Gradle en Kotlin
\n\n# Première étape : construction\nFROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nCOPY src ./src\nRUN gradle build --no-daemon -x test\n\n# Deuxième étape : exécution\nFROM eclipse-temurin:21-jre-alpine\nWORKDIR /app\nCOPY --from=builder /app/build/libs/app.jar app.jar\nEXPOSE 8080\nENTRYPOINT ["java", "-jar", "app.jar"]\n\nL'utilisation de eclipse-temurin:21-jre-alpine au lieu d'une image JDK complète réduit la taille de plus de 400 Mo à environ 120 Mo. Pour les applications Kotlin avec Ktor ou Spring Boot, c'est plus que suffisant.
Optimisation de la mise en cache des couches
\n\nPour accélérer les constructions répétées, copiez les dépendances séparément du code source :
\n\nFROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\n# D'abord les dépendances (mises en cache si inchangées)\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN gradle dependencies --no-daemon\n# Ensuite les sources\nCOPY src ./src\nRUN gradle build --no-daemon -x test\n\nCette astuce est particulièrement utile en CI/CD, où chaque seconde compte.
\n\n2. Optimisation des images pour les applications Kotlin
\n\nOutre le choix de l'image de base, il existe des techniques supplémentaires pour réduire la taille et améliorer la sécurité.
\n\nUtilisation de JLink pour créer une JRE personnalisée
\n\nSi votre application n'utilise qu'une partie des modules du JDK, vous pouvez créer une JRE minimale :
\n\n# Dans l'étape builder\nRUN jlink --module-path /opt/java/openjdk/jmods \\\n --add-modules java.base,java.logging,java.naming,java.sql \\\n --output /custom-jre \\\n --strip-debug --no-man-pages --no-header-files\n\n# Dans l'étape runtime\nFROM alpine:3.19\nCOPY --from=builder /custom-jre /opt/jre\nCOPY --from=builder /app/build/libs/app.jar /app/app.jar\nENV PATH="/opt/jre/bin:${PATH}"\nEXPOSE 8080\nCMD ["java", "-jar", "/app/app.jar"]\n\nLa taille de l'image peut être réduite à 50-70 Mo.
\n\nArchitecture multicouche avec Spring Boot
\n\nSpring Boot 3+ prend en charge la division du fat JAR en couches. Utilisez cela dans le Dockerfile :
\n\nFROM eclipse-temurin:21-jre-alpine AS builder\nWORKDIR /app\nCOPY build/libs/*.jar app.jar\nRUN java -Djarmode=layertools -jar app.jar extract\n\nFROM eclipse-temurin:21-jre-alpine\nWORKDIR /app\nCOPY --from=builder /app/dependencies/ ./\nCOPY --from=builder /app/spring-boot-loader/ ./\nCOPY --from=builder /app/snapshot-dependencies/ ./\nCOPY --from=builder /app/application/ ./\nENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]\n\nDésormais, lors d'une modification du code, seule la couche application est reconstruite, tandis que les dépendances et le chargeur Spring Boot restent en cache.
3. Conteneurisation d'applications Ktor
\n\nKtor est un framework léger pour créer des serveurs asynchrones en Kotlin. Sa conteneurisation a ses particularités.
\n\nDockerfile pour Ktor avec Netty
\n\nFROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN gradle dependencies --