Spring Boot Buildpacks with HealthCheck is breaking Native Image build process

205 Views Asked by At

I am trying to add healthchecks to my Spring Boot application while using Buildpacks as suggested in Spring Boot Build Image with Health Check.

My pom.xml configuration:

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
</plugin>
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <builder>dashaun/builder:tiny</builder>
            <name>${docker-image-name}</name>
            <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>

And my docker-compose.yml configuration:

  catalog-service:
    image: sivaprasadreddy/catalog-service
    container_name: catalog-service
    environment:
      - THC_PATH=/actuator/health
      - THC_PORT=8081
    ports:
      - "8081:8081"
    healthcheck:
      test: [ "CMD", "/cnb/process/health-check" ]
      start_period: 30s
      interval: 5s
      retries: 10

Now when I build the docker image using JVM build (mvn spring-boot:build-image) and run the container using docker-compose with the above-mentioned health check, it works fine.

Problem: The problem is when I try to build a GraalVM Native using mvn -Pnative spring-boot:build-image, it is not building a native image, instead it is building a regular jvm based image.

When I remove <buildpacks>...</buildpacks> config, it is properly building native image.

Should I include any additional buildpacks to support building native image or am I misconfiguring anything?

2

There are 2 best solutions below

4
Daniel Mikusa On BEST ANSWER

There is a different set of buildpacks required to run when you want to build a native image app. Because you're including a <buildpacks> block, you're specifically saying "use this set of buildpacks". That overrides the default selection, which would normally handle automatically selecting the right set of buildpacks (i.e. standard JVM or GraalVM).

If you want to build a native image app, you'll need to switch the <buildpacks> block out, like this.

            <buildpacks>
                <buildpack>urn:cnb:builder:paketo-buildpacks/java-native-image</buildpack>
                <buildpack>gcr.io/paketo-buildpacks/health-checker:latest</buildpack>
            </buildpacks>

Then make sure that you run ./mvnw spring-boot:build-image -Pnative with the native profile enabled. That's required as well.

See the instructions in this sample for an example.

1
Michael On

I assume that for some reason native-image is unable to create a native image when using buildpacks. As a result, it creates a fallback file which requires a JVM to run (see Native Image Compatibility Guide):

If the native-image builder is unable to optimize an application at build time, it generates a so-called “fallback file” that requires a Java VM to run.

You could try to disable the fallback image and see if that works:

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <version>${native.maven.plugin.version}</version>
    <configuration>
        <fallback>false</fallback>
    </configuration>
</plugin>

If not, it may reveal the root cause for the failure.