How to set JVM arguments when running mvn spring-boot:build-image command in Spring Boot 2.3.0 to generate a docker image? How to set JVM arguments when running mvn spring-boot:build-image command in Spring Boot 2.3.0 to generate a docker image? docker docker

How to set JVM arguments when running mvn spring-boot:build-image command in Spring Boot 2.3.0 to generate a docker image?


As of today, you can't set JVM arguments in spring-boot:build-image.

Spring boot build image uses Packeto internally and it accepts following 4 environment variables as mentioned in bellsoft-liberica GitHub.

"BP_JVM_VERSION" : "13.0.1",  "BPL_JVM_HEAD_ROOM" : "10","BPL_JVM_LOADED_CLASS_COUNT" : "35", "BPL_JVM_THREAD_COUNT" : "10"

As alternate option, you can pass JVM arguments when you run the image.

docker run -p 8080:8080 --env JAVA_OPTS="-Xmx300m -Xms200m" -t youImageName

If using Kubernetes, you can configure JVM options at deployment level.

    spec:      containers:      - name: yourapp        image: image path        ports:        - containerPort: 8080        env:        - name: SPRING_PROFILES_ACTIVE          value: "prod"            - name: BPL_JVM_HEAD_ROOM          value: "2"          - name: BPL_JVM_LOADED_CLASS_COUNT          value: "35"          - name: BPL_JVM_THREAD_COUNT          value: "10"          - name: JAVA_OPTS          value: >-                -XX:ReservedCodeCacheSize=40M                -XX:MaxMetaspaceSize=60M                -Xlog:gc                -Xms34m                -Xmx40m                -Xss256k                -XX:MaxRAM=150M

There's a GitHub issue open in Spring boot repository discussing this Failed to change JVM arguments for buildpacked image


Build Back Environment Variables

I tried setting JVM arguments when I started using Spring Boot 2.3 & BuildPacks in November 2020, got nowhere and gave up / put it to one side.

Two weeks ago I picked it up again and purely by chance found this: https://github.com/paketo-buildpacks/environment-variables

Basically, you prefix your environment variable with BPE_APPEND_ and this triggers the Environment Variables Build Pack to append your value to the environment variable.

NB: JAVA_TOOL_OPTIONS is what you want here, not JAVA_OPTS.

I needed to attach a Java Agent to monitor our microservices and something like this build.gradle snippet was what worked:

bootBuildImage {  environment = [    'BPE_DELIM_JAVA_TOOL_OPTIONS' : ' ',    'BPE_APPEND_JAVA_TOOL_OPTIONS' : '-javaagent:my-java-agent.jar'    ]}

I used BPE_DELIM_JAVA_TOOL_OPTIONS to make sure a space was added to the existing value of JAVA_TOOL_OPTIONS before my value was appended (the buildpack also allows you to override or prepend to existing value - see their README).

PS: my value was more like '-javaagent:my-java-agent-${some-dynamic-version}.jar', so I needed double quotes, but that made it a Gradle String which didn't work so I had to write this instead "-javaagent:my-java-agent-${some-dynamic-version}.jar".toString().


As @jeremyt suggests, you can override the value of this property using BPE_OVERRIDE_BPL_JVM_THREAD_COUNT build variable. Example:

bootBuildImage {    environment('BPE_OVERRIDE_BPL_JVM_THREAD_COUNT', '150')}

Sadly, as of now, BPE_DEFAULT_BPL_JVM_THREAD_COUNT does not work (the value is ignored). The downside of BPE_OVERRIDE_BPL_JVM_THREAD_COUNT is that it ignores the environment variable set for runtime (in docker run).