Spring Boot Build Image with Health Check
Asked Answered
A

1

5

I'm building my Docker image using Spring Boot's built in Gradle :bootBuildImage task, which is quite convenient, because I don't have to maintain my own Dockerfile.

The Gradle task uses the Paketo Bionic Base Stack under the hood and will build a layered Docker image just fine.

Now, some orchestration engines like Docker Swarm (or simply Docker Compose for dev purposes) execute health checks within the container. Unfortunately, however, the resulting Spring Boot Docker image doesn't have any health checker tools like curl or wget installed, so something like

version: '3.7'

services:
  springBootApp:
    image: my/springboot/docker-image
    healthcheck:
      test: ["CMD-SHELL", "curl http://localhost:8080/actuator/health"]
       

in docker-compose.yml will fail. (I checked that actuators themselves are working fine)

I know that curl or wget aren't ideal. I was actually hoping that the Paketo Builder would pick up something like this Health Checker BuildPack.

Is there a way to configure my bootBuildImage Gradle task to include that (or a similar) additional BuildPack?

As mentioned above, I'm looking for an easy to maintain solution and don't want to write my own Dockerfile to be able to profit from all the baked in best practices Paketo offers.

Ancel answered 30/3, 2023 at 7:26 Comment(0)
E
12

The Health Checkers buildpack hasn't been added to the main builders just yet, but it is fully available to use with your apps.

Instructions

  1. Modify your build.gradle file:

    tasks.named("bootBuildImage") {
      environment["BP_HEALTH_CHECKER_ENABLED"] = "true"
      buildpacks = ["urn:cnb:builder:paketo-buildpacks/java", "gcr.io/paketo-buildpacks/health-checker:latest"]
    }
    

    This will set an env variable at build time instructing the health-checkers buildpack to participate. It also tells Spring Boot build tools to append the health-checkers buildpack to the list of Java buildpacks that ship in the builder by default.

    NOTE you may want to put in a particular version of health-checkers, that's up to you. It supports standard tag conventions like :1, :1.4, :1.4.0 and :latest so you can pin to latest major/minor or a specific version.

    NOTE there is a breaking change in v2 of the health-checker buildpack see the release notes.

  2. Build. ./gradlew bootBuildImage. You'll see the health checkers buildpack included in detection.

    [creator]     ===> DETECTING
    [creator]     7 of 27 buildpacks participating
    [creator]     paketo-buildpacks/ca-certificates   3.6.0
    [creator]     paketo-buildpacks/bellsoft-liberica 10.0.0
    [creator]     paketo-buildpacks/syft              1.26.0
    [creator]     paketo-buildpacks/executable-jar    6.6.2
    [creator]     paketo-buildpacks/dist-zip          5.5.2
    [creator]     paketo-buildpacks/spring-boot       5.23.0
    [creator]     paketo-buildpacks/health-checker    1.3.1
    ...
    
  3. Optional and for v1 of the health-checker buildpack only. Run pack inspect <image> against the produced image. You can see that health checkers has contributed a health-check process type. With v2 of the health-checker buildpack, it no longer contributes process types, because this caused issues.

    Processes:
      TYPE                  SHELL        COMMAND        ARGS                                               WORK DIR
      web (default)                      java           org.springframework.boot.loader.JarLauncher        /workspace
      executable-jar                     java           org.springframework.boot.loader.JarLauncher        /workspace
      health-check                       thc                                                               /workspace
      task                               java           org.springframework.boot.loader.JarLauncher        /workspace
    
  4. Run your app.

    • For v1 of the health-checker buildpack, run docker run -d --health-cmd /cnb/process/health-check -p 8080:8080 -e THC_PATH=/actuator/health <image>.

    • For v2 of the health-checker buildpack, run docker run -d --health-cmd /workspace/health-check -p 8080:8080 -e THC_PATH=/actuator/health <image>.

    The health checker that's used by default is tiny-health-checker. It has other env variables you can configure but for a Spring Boot app you just need to set the actuator path (unless you have management port set differently, then set THC_PORT=<management-port> also.

If you are a Maven user, the process is very similar. Just substitute these instructions for step #1 and then #2 build with ./mvnw spring-boot:build-image.

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <layers>
                <enabled>true</enabled>
            </layers>
            <image>
                <env>
                    <BP_HEALTH_CHECKER_ENABLED>true</BP_HEALTH_CHECKER_ENABLED>
                </env>
                <buildpacks>
                    <buildpack>urn:cnb:builder:paketo-buildpacks/java</buildpack>
                    <buildpack>gcr.io/paketo-buildpacks/health-checker:latest</buildpack>
                </buildpacks>
            </image>
        </configuration>
    </plugin>
Euphorbia answered 31/3, 2023 at 13:30 Comment(8)
In the future, that will be sufficient. For now, the buildpack has to be added manually.Euphorbia
Thank you for this, because it helped me! Just don't forget to set an environment variable of THC_PORT=<server.port> if you are not running on the default port of 8080.Hortensiahorter
Hi @SteveStorck, Should the THC_PORT be added to environment variable of maven-plugin ?Chrystal
Yes, it's not in the builders yet. It won't hurt anything to add it either, when it's eventually added it'll be OK if you have it also. We still plan to add this at some point, but hit some snags so it's on the back burner for now.Euphorbia
@DanielMikusa Why is --health-cmd neccessary? It should be part of the Docker image., see HEALTHCHECK. Is there any way to do this with Spring Boot Maven Plugin?Bluet
What you're referencing @Bluet is a Dockerfile command. There is no equivalent in buildpacks, so you need to set that run your run the image. It's possible one will be added to the buildpacks spec in the future, and then we can take advantage of that, but for now it needs set docker run or in your K8s config.Euphorbia
I tried this approach but the container is unhealthy. When I inspect the container, I see this error in the healtcheck logs ""Output": "OCI runtime exec failed: exec failed: unable to start container process: exec: \"/cnb/process/health-check\": stat /cnb/process/health-check: no such file or directory: unknown". Is there anyone with the same issue?Rill
@Rill the instructions above were originally written for health-checker v1.x. There has since been a v2 release which has a breaking change, see github.com/paketo-buildpacks/health-checker/releases/tag/v2.0.0. I'll update the post above shortly.Euphorbia

© 2022 - 2024 — McMap. All rights reserved.