为什么容器化 Kotlin 是现代开发者的必备技能?
\n\n想象一下这个场景:你在自己的 MacBook 上编写了一个很棒的 Kotlin 应用程序。一切运行完美。你把代码发给使用 Windows 的同事——数据库连接不上。再发给使用 Linux 的同事——JDK 版本不对。熟悉吗?Docker 一劳永逸地解决了这个问题。
\n\n容器化 Kotlin 应用程序不仅仅是一种流行趋势。这是一种确保你的应用程序在任何机器上都能一致运行的方法:从初级开发人员的笔记本电脑到 AWS 上的生产服务器。在本文中,我们将探讨如何正确地将 Kotlin 应用程序打包到 Docker 镜像中,优化其大小并配置为生产环境使用。
\n\n你将学到什么:
\n- \n
- 如何为使用 Gradle 的 Kotlin 应用程序编写 Dockerfile \n
- 如何将镜像大小缩小 3-5 倍 \n
- 如何使用 Docker Compose 连接 Kotlin + 数据库 \n
- 生产环境容器化的最佳实践 \n
Kotlin 应用程序的基础 Dockerfile
\n\n我们从简单的开始。假设你有一个使用 Gradle 构建的标准 Kotlin 应用程序。首先想到的是——获取 JDK 镜像,复制源代码并启动构建。让我们这样做,但立即考虑最佳实践。
\n\n单体构建(不要在生产环境中这样做)
\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\n这种方法可行,但它有 三个严重缺点:
\n- \n
- 大小:由于使用了完整的 JDK,镜像大小约为 400-500 MB \n
- 缓存:源代码有任何更改,Gradle 都会重新下载依赖项 \n
- 安全性:镜像中保留了运行时不需要的构建工具 \n
优化构建:多阶段构建和缓存
\n\nDocker 的真正魔力在于 多阶段构建。我们将过程分为三个阶段:
\n- \n
- 下载依赖项(可缓存) \n
- 构建应用程序 \n
- 最终的最小化镜像 \n
适用于 Kotlin + Gradle 的正确 Dockerfile
\n\n# Stage 1: 下载依赖项\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: 构建\nFROM dependencies AS build\nCOPY src ./src\nRUN gradle build --no-daemon -x test\n\n# Stage 3: 最终镜像\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\n有什么变化?
\n- \n
- Alpine JRE 代替完整的 JDK——镜像大小减小到约 120 MB \n
- 依赖项缓存——如果 build.gradle.kts 没有更改,Docker 会使用缓存 \n
- 安全性——应用程序以非特权用户身份运行 \n
使用 Gradle Wrapper 构建(推荐方式)
\n\n如果你使用 Gradle Wrapper(你应该使用!),Dockerfile 会变得更加优雅。Wrapper 确保所有开发人员和 CI/CD 环境中的 Gradle 版本保持一致。
\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