mvn spring-boot:run already supports agents to take a list of java agents which need to be started/attached to the running application (https://docs.spring.io/spring-boot/docs/2.4.0/maven-plugin/reference/htmlsingle/#goals-run-parameters-details-agents). This works quite well, but unfortunate the resulting docker image from spring-boot:build-image does not support the configuration of the agents.

I did find a workaround to do this:

  • add the agent as a "normal dependency" to the pom.xml
  • add the agent configuration to JAVA_OPTS environment variable which I pass to the docker run ... command. e.g.:
JAVA_OPTS="-javaagent:/workspace/BOOT-INF/lib/applicationinsights-agent-3.0.0.jar -Djava.security.egd=file:///dev/urandom"

This has a couple of drawbacks: - As I add the agent as a dependency, it will be available in the compile path and also at runtime. In my case it does not seem to be an issue, but i could imagine this to cause issues with classloading in some cases. - I need to know the exact path to the JAR as it is located in the docker image

The advantage on the other side is, that I'm able to control from the outside to whether the agent should be loaded or not.

I think a possible way way to solve this would be to allow some additional artifacts (defined with g:a:v) to be included in the final image at a "well known location". This way I could still activate/deactivate the start of the agent via JAVA_OPTS but the agent itself would not be in the classpath.

Why do i want to control the agent from outside? In my case, I include a monitoring agent from azure (https://docs.microsoft.com/de-de/azure/azure-monitor/app/java-in-process-agent). If I run the docker image locally, I don't want the agent to be started, because it fails if it does not have a valid connection string configured via environment variable. I think the same scenario is valid for e.g. the NewRelic agent (I did not explicitly check this).

Comment From: scottfrederick

Thanks for the suggestion, however Spring Boot is not the right place for this behavior to be implemented.

allow some additional artifacts (defined with g:a:v) to be included in the final image at a "well known location". This way I could still activate/deactivate the start of the agent via JAVA_OPTS but the agent itself would not be in the classpath.

The spring-boot:build-image goal invokes a Cloud Native Buildpacks builder, which bundles buildpacks. The builder and buildpacks are in control of what ends up in the generated image beyond the application code contributed by the Spring Boot plugin. Buildpacks also determine the default run command for the generated image.

In my case, I include a monitoring agent from azure (https://docs.microsoft.com/de-de/azure/azure-monitor/app/java-in-process-agent).

By default, the Spring Boot plugin uses the Paketo CNB builder, which bundles a set of Java buildpacks including an Azure Application Insights buildpack. As described in the Paketo documentation, including the agent in the generated image and activating it at runtime is controlled by the presence of a "binding". There is another description of how this works with the Google Stackdriver APM buildpack in this issue comment.

If I run the docker image locally, I don't want the agent to be started, because it fails if it does not have a valid connection string configured via environment variable.

I'm not sure the buildpack will support this runtime enable/disable behavior currently. If you have questions about how the Azure Application Insights buildpack works, you can ask in the Paketo Slack or open an issue in the buildpack github project.

Comment From: imod

@scottfrederick many thanks! this sounds very interesting and sure is of good help - guess I need to wait for https://github.com/spring-projects/spring-boot/issues/23518 to get this properly resolved...