a pleasant descent into madness

Category: JAVA

Adding jars to the classpath of a java docker container

It is easy to add a jar file to the java classpath by using the command
java -cp path/to/jar myjar.jar

The problem with this approach is that the “-cp” or “-classpath” command will overwrite your default classpath, meaning that you will loose all of the other references that existed in there before, you only have the jars that you reference within the classpath command parameter.

In my case, i wanted to APPEND multiple jars during container startup so they can be referenced by my products plug-ins, so i had to figure out how to open up my jar to enable this , after that, it was very easy to append jars.
In the extracted jar directory structure, you will find that you have a “BOOT-INF\lib” directory.

Any of the lib directories contents are automatically added to the classpath when the program is run.

So we want to create another directory inside the lib directory called “external_lib”

“BOOT-INF\lib\external_lib”.

This folder can now be mounted in a docker compose or run command, the folder in the host filesystem can contain any additional jar files that you want to append to the classpath.

Example compose:

mycontainer:
image: mybaseimage:1.0
volumes:
- .\host\tomount\lib:C:\app\BOOT-INF\lib\external_lib

Attention:

Mounting BOOT-INF\classes\lib will not work!

Running a java program in a docker container

Aka: don’t pack fat jars into your container

This post assumes you are using JDK 15

To run a java program from an image, you still need to provide the fat jar in the container.
You then want to extract the fat jar (jar -extract or unzip) into a separate folder.
You should now have a “BOOT-INF” “META-INF” and maybe other folders depending on your codebase.


Skip extracting the namespace if you already know the exact namespace of your main class.

Find the textfile “MANIFEST.MS” in META-INF and open it up, check to find the “MainClass” definition at the end of the file, keep this value in mind.
If your java project uses the spring boot framework (at least at the 2.x versions) you have to substitute the main class found in the MANIFEST.MS with
org.springframework.boot.loader.PropertiesLauncher

This is because the spring framework uses its own means and structure to pack jar files and bootstraps them with their propertieslauncher.

Now the only step left to do is to call the entrypoint correctly.
ENTRYPOINT java namespace.to.my.mainclass

An example for a correctly build dockerfile calling such a jar looks like so:

FROM adoptopenjdk15_hotspot as builder
WORKDIR /extracted_jar
COPY hostDir/myjar.jar ./
RUN jar -xf myjar.jar
ENTRYPOINT java my.main.class

© 2024 Yavuz-Support Blog

Theme by Anders NorenUp ↑