When running a Java application in a Docker container, it is important to properly configure the JVM memory settings. This is essential to ensure that the application has enough memory to run correctly.
If you don’t specify a value for the
--memory flag when starting a Docker container, the container will be given an automatic default memory limit. The default memory limit depends on how you are running Docker.
If you are using Docker on a system with a Linux kernel that supports Control Groups (Cgroups), the default memory limit for a container is :
This means that if you are running Docker on a system with 2GB of available memory, and you are not running any other containers, the default memory limit for a container will be something like 1.5GB to 1.8GB, depending on the specific version of Docker and the configuration of the host system.
If you are using Docker on a system that does not support Control Groups (Cgroups), such as Windows or macOS, the default memory limit for a container is generally much lower, typically around 2GB.
In general, it is a good idea to specify a value for the
--memory flag when starting a Docker container, to ensure that the container has a consistent amount of memory available to it and to prevent the container from consuming too much memory.
To properly set the JVM heap size in a Docker container, you should use the
-Xmx option and you should also set the
--memory flag when starting the container to set the memory limits for the container. This will ensure that the JVM has enough memory available to allocate the desired amount of heap memory.
Java Memory Configuration examples
After the theory, let’s see a practical example. We will start a Java application with OpenJDK17 that prints the MaxMemory available.
Here’s the Dockerfile:
FROM openjdk:17 COPY ./Example.class /tmp WORKDIR /tmp ENTRYPOINT exec java Example
We will build it first:
docker build -t javatest .
Now execute the Container Image without any memory constraint:
docker run -it javatest Max Heap Size = maxMemory() = 16777216000
Without any setting, the JVM Max Heap size is about 16,77 GB.
Next, let’s set a Memory Constraint on the docker environment with the –memory option:
docker run -it --memory 2g javatest Max Heap Size = maxMemory() = 536870912
As you can see, the JVM can now use up to 536 MB Max Memory.
Next, we will try setting the -Xmx Java option in combination with the Docker –memory :
docker run -it -e JAVA_OPTS="-Xmx1512m" --memory 2g javatest Max Heap Size = maxMemory() = 536870912
What happened ? as you can see the JAVA_OPTS was ineffective to set the Java Max Memory. The reason for that is that JAVA_OPTS is not a standard option to set Java Memory Settings. To use the JAVA_OPTS environment variable, we need to modify the Dockerfile as follows:
FROM openjdk:17 COPY ./Example.class /tmp WORKDIR /tmp ENTRYPOINT exec java $JAVA_OPTS Example
Then, rebuild the image and verify that the -Xmx setting is effective:
docker build -t javatest . docker run -it -e JAVA_OPTS="-Xmx1512m" --memory 2g javatest Max Heap Size = maxMemory() = 1585446912
Finally, if you want to inject the JVM Settings without a change in the Dockerfile, you can use the JAVA_TOOL_OPTIONS. The JAVA_TOOL_OPTIONS is recognized by all JVM Container images. For example:
docker run -it -e JAVA_TOOL_OPTIONS="-Xmx1512m" --memory 2g javatest Picked up JAVA_TOOL_OPTIONS: -Xmx1512m Max Heap Size = maxMemory() = 1585446912
This article discussed the basics of setting Java memory in a Docker container. Please note that Java Container Image, such as WildFly Container Image, may have specific environment variables to set the Java Memory. For example: Configuring JVM settings on Openshift