If I do docker run --memory=X
to run a Java app through a Bash script, is there any way to get this Bash script to reliably infer how much memory has been allocated to the container? Basically, I want this Bash script to do something like:
#!/bin/bash
# (Do some other stuff...)
MAX_RAM="$(get-max-ram)"
exec java "-Xms${MAX_RAM}" "-Xmx${MAX_RAM}" -jar my_jar.jar
Also, if I do the above, should I make Java use a little bit less than the maximum RAM?
java5/6/7/8u131-: a simple but efffective method, You can use
java -Xmx cat /sys/fs/cgroup/memory/memory.limit_in_bytes
(except windows)java8u131+ and java9+:
-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
would do the job.java 8u191+:
UseContainerSupport
is turned on by default. This feature is backported from java10, but it hasn't been backported to java9 so far.java10+:
UseContainerSupport
is turned on by default.Ref:
Docker uses cgroups to implement resource limits. Inside the container, you can use the
cgget
utility, to print parameters of various subsystems (in this instance, thememory
subsystem).For example, consider a container started with a memory limit of 64G (it's Java, after all):
Within the container, then use
cgget
to read the current value of thememory.limit_in_bytes
parameter:Note that you'll probably have to install the
cgget
binary via the container image's package manager first. On Ubuntu, you'll need thecgroup-bin
package.You can then use this value to dynamically compute your JVM parameters (just as an example, adjust to your own needs):
Important: When run without memory restriction (i.e. without
--memory=X
flag), thememory.limit_in_bytes
parameter will still have a value, although of the magnitude of around 2^63 - 4096:Unless you want to start your JVM with a minimum heap space of about 8 EB, your entrypoint script should also consider this case: