Docker与Kotlin:高级应用容器化

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Docker与Kotlin:高级应用容器化

\n\n

容器化已成为现代开发中不可或缺的一部分,Kotlin也不例外。如果你已经掌握了基本的Dockerfile和简单JAR文件的启动,那么是时候进入下一个层次了。本文将探讨Kotlin应用容器化的高级技术:多阶段构建、镜像大小优化、针对Ktor和Spring Boot框架的配置,以及在生产环境中使用Docker Compose。

\n\n

1. Kotlin应用的多阶段构建

\n\n

容器化JVM应用的主要问题之一是最终镜像的大小。标准的OpenJDK镜像可能超过400MB。多阶段构建允许将构建环境与运行环境分离,使用最小的运行时镜像。

\n\n

Kotlin Gradle项目示例

\n\n
# 第一阶段:构建\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# 第二阶段:运行\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\n

使用eclipse-temurin:21-jre-alpine代替完整的JDK镜像,可将大小从400+MB减少到约120MB。对于基于Ktor或Spring Boot的Kotlin应用来说,这已经绰绰有余。

\n\n

优化层缓存

\n\n

为了加速重复构建,请将依赖项与源代码分开复制:

\n\n
FROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\n# 先处理依赖项(如果未更改则缓存)\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN gradle dependencies --no-daemon\n# 再处理源代码\nCOPY src ./src\nRUN gradle build --no-daemon -x test
\n\n

这一技巧在CI/CD中尤其有用,因为每一秒都至关重要。

\n\n

2. Kotlin应用镜像优化

\n\n

除了选择基础镜像外,还有其他技术可以减小镜像大小并提高安全性。

\n\n

使用JLink创建自定义JRE

\n\n

如果你的应用只使用JDK的部分模块,可以创建一个最小的JRE:

\n\n
# 在构建阶段\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# 在运行阶段\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\n

镜像大小可以降低到50-70MB。

\n\n

Spring Boot的多层架构

\n\n

Spring Boot 3+支持将fat JAR拆分为多个层。在Dockerfile中使用此功能:

\n\n
FROM 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\n

现在,当代码更改时,只有application层会重新构建,而依赖项和Spring Boot加载器则保持缓存状态。

\n\n

3. Ktor应用的容器化

\n\n

Ktor是一个用于在Kotlin中创建异步服务器的轻量级框架。其容器化有自身的特点。

\n\n

使用Netty的Ktor的Dockerfile

\n\n
FROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN gradle dependencies --                

博客

书籍推荐