Warum ist die Containerisierung von Kotlin ein Must-have für moderne Entwickler?
\n\nStellen Sie sich folgende Situation vor: Sie haben eine coole Kotlin-Anwendung auf Ihrem MacBook geschrieben. Alles funktioniert perfekt. Sie geben den Code an einen Kollegen unter Windows weiter – die Datenbank verbindet sich nicht. An einen weiteren unter Linux – die JDK-Version stimmt nicht. Kommt Ihnen bekannt vor? Docker löst dieses Problem ein für alle Mal.
\n\nDie Containerisierung von Kotlin-Anwendungen ist nicht nur ein modischer Trend. Es ist eine Möglichkeit, sicherzustellen, dass Ihre Anwendung auf jeder Maschine gleich funktioniert: vom Laptop eines Junioren bis zum Produktionsserver in AWS. In diesem Artikel werden wir uns ansehen, wie man eine Kotlin-Anwendung richtig in ein Docker-Image packt, seine Größe optimiert und für die Produktion konfiguriert.
\n\nWas Sie lernen werden:
\n- \n
- Wie man ein Dockerfile für eine Kotlin-Anwendung mit Gradle schreibt \n
- Wie man die Image-Größe um das 3- bis 5-fache reduziert \n
- Wie man Docker Compose für die Kombination Kotlin + Datenbank verwendet \n
- Best Practices für die Produktions-Containerisierung \n
Basis-Dockerfile für eine Kotlin-Anwendung
\n\nBeginnen wir einfach. Angenommen, Sie haben eine Standard-Kotlin-Anwendung, die mit Gradle gebaut wird. Das Erste, was einem in den Sinn kommt, ist, ein JDK-Image zu nehmen, die Quellen zu kopieren und den Build zu starten. Machen wir das, aber gleich unter Berücksichtigung der Best Practices.
\n\nMonolithischer Build (machen Sie das nicht in der Produktion)
\n\n# Dockerfile\nFROM gradle:7.6-jdk17 AS build\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nCOPY src ./src\nRUN gradle build --no-daemon -x test\n\nFROM openjdk:17-jdk-slim\nWORKDIR /app\nCOPY --from=build /app/build/libs/app.jar app.jar\nEXPOSE 8080\nCMD ["java", "-jar", "app.jar"]\n\nDieser Ansatz funktioniert, hat aber drei schwerwiegende Nachteile:
\n- \n
- Größe: Das Image wiegt aufgrund des vollständigen JDK etwa 400-500 MB \n
- Caching: Bei jeder Änderung der Quellen lädt Gradle die Abhängigkeiten erneut herunter \n
- Sicherheit: Im Image verbleiben Build-Tools, die zur Laufzeit nicht benötigt werden \n
Optimierter Build: Multi-Stage und Caching
\n\nDie wahre Magie von Docker sind Multi-Stage-Builds. Wir teilen den Prozess in drei Phasen auf:
\n- \n
- Herunterladen der Abhängigkeiten (wird gecached) \n
- Build der Anwendung \n
- Finales minimales Image \n
Richtiges Dockerfile für Kotlin + Gradle
\n\n# Stage 1: Herunterladen der Abhängigkeiten\nFROM gradle:7.6-jdk17 AS dependencies\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN gradle dependencies --no-daemon\n\n# Stage 2: Build\nFROM dependencies AS build\nCOPY src ./src\nRUN gradle build --no-daemon -x test\n\n# Stage 3: Finales Image\nFROM eclipse-temurin:17-jre-alpine\nWORKDIR /app\nCOPY --from=build /app/build/libs/app.jar app.jar\nRUN addgroup -S appgroup && adduser -S appuser -G appgroup\nUSER appuser\nEXPOSE 8080\nCMD ["java", "-jar", "app.jar"]\n\nWas hat sich geändert?
\n- \n
- Alpine JRE anstelle des vollständigen JDK – das Image schrumpft auf ~120 MB \n
- Caching von Abhängigkeiten – wenn sich build.gradle.kts nicht ändert, verwendet Docker den Cache \n
- Sicherheit – die Anwendung wird von einem unprivilegierten Benutzer gestartet \n
Build mit Gradle Wrapper (empfohlene Methode)
\n\nWenn Sie den Gradle Wrapper verwenden (und das sollten Sie!), wird das Dockerfile noch eleganter. Der Wrapper stellt sicher, dass die Gradle-Version bei allen Entwicklern und in CI/CD gleich ist.
\n\nFROM eclipse-temurin:17-jdk-alpine AS builder\nWORKDIR /app\nCOPY gradlew gradlew.bat ./\nCOPY gradle ./gradle\nRUN ./gradlew --version\n\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN ./gradlew dependencies --no-daemon\n\nCOPY src ./src\nRUN ./gradlew build --no-daemon -x test\n\nFROM eclipse-temurin:17-jre-alpine\nWORKDIR /app\nCOPY --from=builder