2

SO I am trying to change the JVM heap memory percentage I have added these two lines in my Dockerfile

ENV JAVA_OPTS="--XX:MinRAMPercentage=50.0 --XX:MaxRAMPercentage=80.0"
CMD ["--spring.profiles.active=${profile}","${JAVA_OPTS}"]

But when I check this command:(java -XX:+PrintFlagsFinal -version | grep -E "UseContainerSupport | InitialRAMPercentage | MaxRAMPercentage | MinRAMPercentage") on my docker container, it shows default values of the above parameter: enter image description here

HMT
  • 2,093
  • 1
  • 19
  • 51
  • Can you show the `docker run` command you use? – quoc9x Oct 11 '22 at 13:22
  • I have pushed the docker image to ECR and created a task definition which is pulling this image and running it in ECS so I am not running the container manually – HMT Oct 11 '22 at 13:25
  • Can you run the image locally, to check if the image itself is fine? If locally all is fine, then somewhere in ECR-world the same env-var will be set. – akop Oct 11 '22 at 13:30
  • 2
    something in the startup script / entrypoint / run command must actively include `JAVA_OPTS`, that's not a builtin Java feature, just a common environment variable name used in many startup scripts, `JAVA_TOOL_OPTIONS` https://stackoverflow.com/a/58355963/995891 on the other hand seems to be a property picked up by the jvm by itself. And I think `"${JAVA_OPTS}"` isn't evaluated because https://stackoverflow.com/a/47573374/995891 – zapl Oct 11 '22 at 13:35
  • What does your ENTRYPOINT look like? You need a shell to be able to do environment variable substitution. – Hans Kilian Oct 11 '22 at 14:20
  • if you use spring boot, there's a nice guide on how to build docker images here: https://spring.io/guides/topicals/spring-boot-docker in the end even ones that configure jvm parameters dynamically (via https://github.com/cloudfoundry/java-buildpack-memory-calculator) – zapl Oct 11 '22 at 14:56
  • @zapl This link helped me resolve the issue I added ENV JAVA_TOOL_OPTIONS "-XX:MinRAMPercentage=50.0 -XX:MaxRAMPercentage=80.0" and it worked. – HMT Oct 12 '22 at 06:33
  • 1
    Have you checked if your `spring.profiles.active` works? You can use `SPRING_PROFILES_ACTIVE` in env as well in case that has the same problem – zapl Oct 12 '22 at 10:59
  • @zapl it is working, can you pls post your comment as answer so that I can accept it – HMT Oct 12 '22 at 13:34

1 Answers1

3

No environment variable expansion or other processing is done on exec form CMD (or ENTRYPOINT or RUN). Your application is getting invoked with literally the strings --spring.profiles.active=${profile} and ${JAVA_OPTS}, and you will see these including the ${...} markers in your Java program's main() function.

Docker's normal assumption here is that any expansion like this will be done in a shell, and shell form CMD will wrap its string in /bin/sh -c '...' so this happens. However, this setup isn't compatible with splitting ENTRYPOINT and CMD: due to the mechanics of how the two parts are combined neither part can be wrapped in a shell if you're using the "container as command" pattern where the CMD is just an argument list.

The easiest way to handle this is to ignore ENTRYPOINT entirely; put all of the command and arguments into CMD; and use the shell form rather than the exec form.

ENV JAVA_OPTS="--XX:MinRAMPercentage=50.0 --XX:MaxRAMPercentage=80.0"
# no ENTRYPOINT; shell form of CMD
CMD java ${JAVA_OPTS} -jar /app/app.jar --spring.profiles.default=${profile}

If you docker run a temporary debugging container on this image, it will see the environment variable but the command you provide will replace the image's CMD.

docker run --rm your-image \
  /bin/sh -c 'echo $JAVA_OPTS'
# prints the environment setting

Correspondingly if you run a separate java, it won't see the options that are only provided in the image's CMD. (Similarly try running java -XX:MaxRamPercentage=80.0 in one terminal window, and java -XX:+PrintFlagsFinal with no other options in another window, and the second invocation won't see the JVM options from the first JVM; the same mechanics apply to Docker containers.)

David Maze
  • 130,717
  • 29
  • 175
  • 215