Search code examples
spring-webfluxbuildpackpaketo

Are the any buildpacks that generate Spring Webflux optiimized OCI Images?


I'm unable to find a buildpack builder that lends itself to Spring Webflux applications. Paketo, for example, has little room for customization and out of the box includes buildpacks that are not needed for a typical Webflux app (e.g. apache-tomcat). Are there any buildpacks tailored for webflux/jvm-reactive applications?


Solution

  • It doesn't look like you need to do anything specific here for Spring Webflux, the Java related CNBs will just do the right thing.

    I took a sample app that I created with Spring Initializer (just added the Webflux starter) and ran pack build against it (if you run ./mvnw spring-boot:build-image, you should get very similar output).

    That gave me the following output:

    ===> DETECTING
    [detector] 6 of 17 buildpacks participating
    [detector] paketo-buildpacks/bellsoft-liberica 3.2.0
    [detector] paketo-buildpacks/maven             3.1.0
    [detector] paketo-buildpacks/executable-jar    3.1.0
    [detector] paketo-buildpacks/apache-tomcat     2.2.0
    [detector] paketo-buildpacks/dist-zip          2.2.0
    [detector] paketo-buildpacks/spring-boot       3.2.0
    

    At first glance, that might seem odd. Why is Tomcat there? Looking at the Tomcat CNB, that is expected though. The Tomcat CNB is always going to return a successful detection.

    Note how pass is hard coded to true.

    result := libcnb.DetectResult{
        Pass: true,
        Plans: []libcnb.BuildPlan{
            {
                Requires: []libcnb.BuildPlanRequire{
                    {Name: "jre", Metadata: map[string]interface{}{"launch": true}},
                    {Name: "jvm-application"},
                },
            },
        },
    }
    

    The reason this is OK is because at build time, the Tomcat CNB will immediately exit (no-op) if there is no WEB-INF directory, and for a Spring WebFlux app there won't be.

    file := filepath.Join(context.Application.Path, "WEB-INF")
    if _, err := os.Stat(file); err != nil && !os.IsNotExist(err) {
        return libcnb.BuildResult{}, fmt.Errorf("unable to stat file %s\n%w", file, err)
    } else if os.IsNotExist(err) {
        return libcnb.BuildResult{}, nil
    }
    

    You can confirm this by looking at the full output of pack build and looking for the presence of Paketo Apache Tomcat Buildpack x.x.x (where x.x.x is the version number). If the Tomcat CNB were running and performing any work, you'd see that line output.

    The paketo-buildpack/dist-zip CNB works the same way, it's just looking for <APPLICATION_ROOT>/*/bin/* to exist.

    So in summary, the image that's generated should be specific to your application and shouldn't contain unnecessary stuff. If you're running Spring WebFlux, then you shouldn't have Tomcat installed into your image. In addition, you get all the optimizations provided by using Cloud Native buildpacks.