Docker und Kotlin: Containerisierung von Anwendungen von A bis Z
Containerisierung ist zum De-facto-Standard für die moderne Softwareentwicklung geworden. Sie löst das Problem "bei mir funktioniert es" und vereinfacht CI/CD. In diesem Artikel werden wir uns ansehen, wie man Kotlin-Anwendungen effektiv mit Docker containerisiert – von der Erstellung eines einfachen Dockerfile bis hin zu Produktionsoptimierungen und Orchestrierung.
1. Grundlagen: Dockerfile für eine Kotlin-Anwendung
Das Herzstück der Containerisierung ist das Dockerfile. Für Kotlin-Anwendungen, die in JVM-Bytecode kompiliert werden, verwenden wir einen mehrstufigen Build (Multi-Stage Build). Dadurch wird die Build-Umgebung von der Laufzeitumgebung getrennt, was die Größe des endgültigen Images reduziert.
Betrachten wir eine typische Kotlin-Anwendung mit Gradle (die Datei build.gradle.kts ist vereinfacht):
// build.gradle.ktsplugins { kotlin("jvm") version "1.9.0" application id("com.google.cloud.tools.jib") version "3.4.0" // optional}
application { mainClass.set("com.example.MainKt")}Erstellen wir ein Dockerfile mit zwei Stufen:
# Stufe 1: BuildFROM gradle:8.5-jdk21 AS builderWORKDIR /appCOPY build.gradle.kts settings.gradle.kts ./COPY gradle ./gradleCOPY src ./srcRUN gradle build --no-daemon
# Stufe 2: AusführungFROM eclipse-temurin:21-jre-alpineWORKDIR /appCOPY --from=builder /app/build/libs/my-app-*.jar app.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "app.jar"]Befehle zum Bauen und Ausführen:
docker build -t my-kotlin-app .docker run -p 8080:8080 my-kotlin-appEmpfehlungen:
- Verwenden Sie
eclipse-temurin(OpenJDK) anstelle des vollständigen JDK – das Image ist kleiner. - Cachen Sie Abhängigkeiten: Kopieren Sie zuerst
build.gradle.kts, dannsrc. - Für Spring Boot-Anwendungen können Sie
layersfür inkrementelle Builds verwenden.
2. Optimierung mit Jib und Gradle
Das manuelle Schreiben eines Dockerfile ist der klassische Weg, aber es gibt Tools, die den Prozess automatisieren. Jib (von Google) integriert sich in Maven/Gradle und erstellt optimierte Docker-Images ohne Docker-Daemon.
Fügen Sie das Jib-Plugin in build.gradle.kts hinzu:
plugins { id("com.google.cloud.tools.jib") version "3.4.0"}
jib { from { image = "eclipse-temurin:21-jre-alpine" } to { image = "my-registry/my-kotlin-app:latest" } container { ports = listOf("8080") jvmFlags = listOf("-Xms512m", "-Xmx1024m") }}Build mit einem Befehl:
./gradlew jibDockerBuildVorteile von Jib:
- Automatische Aufteilung in Schichten (Abhängigkeiten, Ressourcen, Klassen).
- Benötigt kein Dockerfile.
- Funktioniert ohne Docker-Daemon – ideal für CI/CD.
Beispiel einer Kotlin-Anwendung (einfacher HTTP-Server):
// src/main/kotlin/com/example/Main.ktpackage com.example
import com.sun.net.httpserver.HttpServerimport java.net.InetSocketAddress
fun main() { val server = HttpServer.create(InetSocketAddress(8080), 0) server.createContext("/") { exchange -> val response = "Hello from Kotlin in Docker!" exchange.sendResponseHeaders(200, response.length.toLong()) exchange.responseBody.write(response.toByteArray()) exchange.close() } server.start() println("Server started on port 8080")}3. Docker Compose: Multi-Container-Anwendungen
Reale Projekte bestehen selten aus nur einem Dienst. Docker Compose ermöglicht es, mehrere Container zu beschreiben und auszuführen (z. B. Anwendung + Datenbank + Redis).
Erstellen wir eine docker-compose.yml für eine Kotlin-Anwendung mit PostgreSQL:<