How to build and configure custom JRE for Java Spring web application in Docker Image/containers
I am building my Java API server into a Docker image.
I am making my own custom JRE using this:
Then copying into a scratch container image so there is nothing else. I would like to keep it this way to minimize attack vectors and keep the image size on the smaller side as much as possible.
I am unfamiliar with Java applications, this is the first time I'm building an application with Java and I'd like to learn best practices.
What are some common arguments to pass into the JVM when you run your application in a container? I read briefly about how you should set the heap sizes and put on container support to prevent the JVM from adjusting the max heap size when running in a container.
Is this advised? What else would you run in addition to the container support and heap size arguments?
The goal is to keep attack vectors small while still maintaining good performance.
At the end, this is what I have for my final image:
43 Replies
⌛ This post has been reserved for your question.
Hey @DaMango! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./closeor theClose Postbutton above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
Then copying into a scratch container image so there is nothing else. I would like to keep it this way to minimize attack vectors and keep the image size on the smaller side as much as possible.I don't think a jlink'ed package would work with
FROM scratch as it needs some things present on the system - at least libcit seems to run at least?
oh, it does?
ya
I think the JRE includes various DLLs
let me look
it would be .so files
but I didn't think it would include libc
if you really want to have it minimal, you could use native-image
That is the full dockerfile.
edit:
The below is more for debugging capabilities
I add
because sometimes i want to inspect with bash and otherwise there is no terminal in the container image. However, the image also runs without including these, which I'm planning to take out for the production image
oh I didn't see these
yeah then it might not be as minimal lol
The image works without the
/lib64 and those linesWhat does the application do?
its a spring boot web application
ok
i haven't programmed anything, i wanted to get the container image pipeline set up
so I can do automated integration testing a bit easier
Does it serve HTTP request with that image?
I haven't tried yet haha
I think my issue was my gradle build file wasn't including the netty server or tomcat server
try it before thinking about JVM arguments
that seems like it would be useful in the container image?
Does it work on your host?
no
it runs and exits with exit code 0
then you should get that working before the Docker image
is shadowJar a good tool to use? I was looking to create a fatJar
that might be also something that can happen in the Docker image because of using
FROM scratchor something that is a little more self-contained
If you really want to build a single JAR file that contains the application, it's an option but I wouldn't recommend that approach
what would you recommend
One of the following:
- Use Spring's tooling for packaging the app as a JAR
- Copy the application and dependency JAR in one directory and run it from there
- you could also use an exploded format
- If you really want a Docker image that's as minimal as possible (at the cost of creating that file taking a few minutes and quite a bit more CPU/memory), you can try native-image. With that (and static linking with musl), you might even be able to make the last stage look like this (while Spring supports native-image, idk whether it works with static linking):
but before you work on packages, you should at least have a running application that is at least able to serve HTTP requests. It doesn't need to be able to do anything useful/have any custom code but you need some way of testing whether it actually works
and for JVM arguments, you should probably tune them once you see what the application actually needs
so when I just run a
./gradlew clean build with the spring boot plugin it produces a few different jar files. Do you know what these usually might be?
important JVM arguments will probably be the heap size and the selection of which GC to use
the
-all.jar is basically a fat JAR containing everything necessary
I think the normal one is probably only the application code
and idk the difference between the normal JAR and the -plain.jar
I guess it first created the -plain.jar and then the Spring plugin did some transformation
but I normally use Maven lolah gotcha
sorry i'm still learning java so i am still trying to learn about how everything fits together
that is java specific
i'll make a small http endpoint to test if it is working
i think building normally includes a tomcat server
What exactly? Maven and Gradle are build tools that are mostly (but not solely) used for Java/JVM applications. The Spring plugin is spring specific
I think that even without an endpoint, it should serve HTTP requests (you'd just get 404s)
at least as long as you have the web started added
well things like building JARs, JVM configuration, configuring tomcat/netty
since i'm used to just building binaries with shared libraries
or python/interpretted languages
@dan1st | Daniel tomcat is the default for spring boot applications, would you ever recommend using netty over tomcat for spring boot apps?
or what have you seen there
I think netty is the default for reactive Spring Boot Web applications
but I could be wrong on that
oh i think you are right
These are all JVM specific and other languages do their own thing
i don't think i'm using reactive spring boot?
if there's nothing saying "reactive" or "reactor" in your build.gradle, you aren't
i think i just put down the spring boot gradle plugin and the web app starter
and it will be more convenient without reactive stuff
if you need the scalability, you can enable virtual threads
And plugins:
yeah that's non-reactive
💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping.
Warning: abusing this will result in moderative actions taken against you.