如何使用Gradle构建仅含依赖的JAR 适配Kaniko Docker缓存优化
Gradle项目依赖与代码分离的Kaniko缓存优化方案
1. 实现依赖与应用代码分离打包
首先在项目的build.gradle文件中添加如下配置,即可将第三方依赖和应用代码构建为独立的文件,无需修改原有打包逻辑:
// 新增任务:导出所有第三方依赖到 build/dependencies 目录 task copyDependencies(type: Copy) { from configurations.runtimeClasspath into "${buildDir}/dependencies" } // 调整原有jar任务:仅打包应用自身代码,不包含任何第三方依赖 jar { dependsOn copyDependencies archiveBaseName = "application" from sourceSets.main.output }
执行./gradlew build命令完成构建后,build/dependencies目录下会存放所有项目依赖的JAR包,build/libs/application.jar为仅包含应用业务代码的JAR包,二者完全独立。
2. 适配Kaniko缓存规则的Dockerfile编写
Kaniko会为Dockerfile中的每一条COPY/RUN/ADD命令生成独立的缓存层,只要对应命令的输入没有变化,就会直接命中缓存跳过执行。你可以根据缓存粒度需求选择以下两种写法:
2.1 常规分层缓存写法
该写法实现简单,能满足90%以上场景的缓存需求:
FROM openjdk:11-jre-slim WORKDIR /app # 先复制依赖层:只要依赖不变,该层永远命中缓存 COPY build/dependencies/*.jar ./ # 再复制应用代码层:只有代码变动时才会重建该层 COPY build/libs/application.jar ./ ENTRYPOINT ["java", "-jar", "application.jar"]
2.2 逐个复制JAR的极致缓存写法
如果需要实现单个依赖更新不影响其他依赖的缓存,可以在构建前动态生成逐个复制依赖的Dockerfile指令:
- 执行构建前先运行以下命令,生成所有依赖对应的COPY指令并追加到Dockerfile中:
ls build/dependencies/*.jar | awk '{print "COPY "$1" /app/"}' >> Dockerfile
- 最终的Dockerfile结构示例如下,每个依赖对应独立的缓存层:
FROM openjdk:11-jre-slim WORKDIR /app # 以下为动态生成的逐个COPY依赖的指令 COPY build/dependencies/lombok-1.18.30.jar /app/ COPY build/dependencies/spring-core-5.3.29.jar /app/ COPY build/dependencies/jackson-databind-2.15.2.jar /app/ # ... 其余依赖的COPY指令 # 最后复制应用代码包 COPY build/libs/application.jar ./ ENTRYPOINT ["java", "-jar", "application.jar"]
这种写法下,单个依赖版本更新只会让对应COPY命令的缓存失效,其余所有依赖的缓存都可以正常命中,缓存命中率最大化。
内容的提问来源于stack exchange,提问作者shmish111
相关产品推荐
相关产品推荐

