如何在Bazel的java_binary规则中拆分_deploy.jar内的依赖与自有代码
最优Bazel侧实现方案
方案1:使用原生java_binary的deploy_env参数(零额外开发成本,最推荐)
Bazel原生java_binary规则内置的deploy_env参数正是为这种场景设计的:该参数指定的目标及其所有传递依赖,都不会被打包进最终的_deploy.jar产物中。
你只需要修改原有java_binary配置,增加一行deploy_env声明即可:
java_library( name = "mylib", srcs = ..., deps = ... ) java_binary( name = "mybin", main_class = ..., runtime_deps = ["//:mylib"], # 新增这一行,指定mylib及其传递依赖不打入deploy jar deploy_env = ["//:mylib"], )
修改后执行构建:
bazel build //:mybin_deploy.jar得到的产物仅包含所有第三方依赖,无任何自有业务代码,大小约198.5MBbazel build //:mylib得到的libmylib.jar就是你的业务代码包,大小约1.5MB
Dockerfile可以直接简化,去掉额外的zip处理阶段:
FROM openjdk:18-slim-buster WORKDIR /app CMD ["java", "-cp", "/app/mybin_deps.jar:/app/mylib.jar", "com.Main"] COPY mybin_deploy.jar /app/mybin_deps.jar COPY libmylib.jar /app/mylib.jar
该方案完全复用Bazel原生能力,不需要任何自定义规则开发,也避免了手动修改jar包可能带来的文件损坏、路径匹配错误等问题。
方案2:使用rules_docker直接构建分层镜像(Docker集成更顺滑)
如果你需要直接用Bazel输出Docker镜像,可以使用官方的rules_docker规则集中的java_image规则,它会自动将第三方依赖、自有代码拆分为独立的镜像层,依赖未发生变化时,镜像推送只会上传1.5MB的业务代码层。
配置示例:
load("@io_bazel_rules_docker//java:image.bzl", "java_image") java_image( name = "mybin_image", binary = ":mybin", main_class = "com.Main", base = "@openjdk_18_slim_buster//image", )
直接执行bazel build //:mybin_image即可得到符合要求的分层镜像。
内容的提问来源于stack exchange,提问作者Matt McMinn
相关产品推荐
相关产品推荐

