salesforce / rules_spring

Bazel rule for building Spring Boot apps as a deployable jar
BSD 3-Clause "New" or "Revised" License
224 stars 48 forks source link

Implement Docker/OCI layer index file support #69

Open plaird opened 3 years ago

plaird commented 3 years ago

Spring Boot 2.3 added the ability to supply a layer index file that optimizes the writing of the Spring Boot jar for container use cases. It splits the jar into multiple layers.

Much like the classpath index file #33, we need to add an attribute so the user can supply the layer index. I don't think we should do anything magical here (i.e. auto-generating these files). Just allow the user to specify an existing workspace file as an attribute in the rule. This would be optional as the default layout seems sufficient for most use cases.

But then the writing of the spring boot jar file needs to honor the layers. This will involve having an alternate layout. This article explains everything pretty well:

To make this useful, the user would then need to create a docker image from the layered jar. This involves the -Djarmode=layertools tool. It is questionable if we should provide docker image creation support for this or not. At this point, I am more in favor of just showing examples.

This work may require changing the springboot rule signature in some incompatible way, so assigning to a major release for now.

chrismgrayftsinc commented 3 years ago

One thing that might be nice would be to have a springboot_image rule similar to the rules in bazelbuild/rules_docker (or even building on them). I have been using those rules and they work well -- it just takes a long time to upload a new image even when very little has changed.

plaird commented 3 years ago

Thanks for feedback. We also use rules_docker to package up our springboot apps, and have had good success with it.

I am a little worried about building too much into the rules_spring repo, so I am not sold on springboot_image. But it is worth looking into it for sure. We are finding that external rules that bring in other dependencies (e.g. if rules_spring depended on rules_docker) are a pain to deal with. Bazel Federation just didn't take off unfortunately.

What I have on the books right now is Issue #94 which is to just provide an example of how to build the docker image by combining springboot rule with rules_docker rules. But, once we implement this layer support, there may be a useful reason to also provide a springboot_image rule so we should consider it.

Marcus-Rosti commented 3 years ago

@plaird do you have an example of that just for yourself? is it as easy adding the target and main to a container_image?

chrismgrayftsinc commented 3 years ago

@Marcus-Rosti we use

container_image(
    name = "foo-service-image",
    base = "@java_base//image",
    cmd = [
        "java",
        "-jar",
        "foo-service.jar",
    ],
    files = ["foo-service.jar"],
    ports = [
        "8080",
        "8081",
    ],
)

where @java-base is

container_pull(
    name = "java_base",
    digest = "sha256:0ee3964303ce4c8d8b371457ebeca218c74b240b6740bb9f82b0606e9b56a7f5",
    registry = "index.docker.io",
    repository = "library/openjdk",
)
Marcus-Rosti commented 3 years ago

and @chrismgrayftsinc foo-service.jar is the output of


java_library(
    name = "mrosti_server",
    srcs = ["App.java"],
    deps = [
        "//my/service...",
    ] + springboot_deps,
)

springboot(
    name = "mrosti_server",
    boot_app_class = "com.marcus.rosti.App",
    java_library = "mrosti_server",
)

container_image(
...
    files = ["foo-service.jar"], # output of above?
)
chrismgrayftsinc commented 3 years ago

In this case, it looks like it would be the output of the springboot rule (which would need a different name from your library). Assuming you named the springboot rule "mrosti-service", then "foo-service.jar" would be replaced by "mrosti-service.jar".

Marcus-Rosti commented 3 years ago

@chrismgrayftsinc that worked like a charm! thanks!

plaird commented 3 years ago

Thanks @Marcus-Rosti for the question, and @chrismgrayftsinc for providing the example. Internally we do some additional fancy pants stuff around custom entrypoints, but what Chris provided covers the 95% case.

chrismgrayftsinc commented 3 years ago

@plaird I went ahead and started a small repo that does this. I heavily modified the springboot.bzl file to do it. I will need to clean it up, but for now it appears to work for our use case. Check it out at https://github.com/chrismgrayftsinc/rules_spring_image

plaird commented 3 years ago

@chrismgrayftsinc I am looking forward to look at your solution. This week is crazy, but I am hoping to get to this soon. Thanks!

plaird commented 3 years ago

@chrismgrayftsinc I think you are underselling what you have done - it is more than just layer file support. You also have done a bunch of the needful of migrating off of bash #3 which is the oldest open issue in the project. :) I have a bunch of things in flight right now outside of rules_spring, but I will try to prioritize finding a way to merge your work. I was thinking of using Java based on singlejar for the new rule impl in #3, but if we can get there with Starlark all the better.