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?
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, the memory
subsystem).
For example, consider a container started with a memory limit of 64G (it's Java, after all):
> docker run --memory=64G
Within the container, then use cgget
to read the current value of the memory.limit_in_bytes
parameter:
> cgget -nvr memory.limit_in_bytes /
68719476736
Note that you'll probably have to install the cgget
binary via the container image's package manager first. On Ubuntu, you'll need the cgroup-bin
package.
You can then use this value to dynamically compute your JVM parameters (just as an example, adjust to your own needs):
MAX_RAM=$(cgget -nvr memory.limit_in_bytes /)
JVM_MIN_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.2" | bc))
JVM_MAX_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.8" | bc))
exec java "-Xms${JVM_MIN_HEAP}" "-Xmx${JVM_MAX_HEAP}" -jar my_jar.jar
Important: When run without memory restriction (i.e. without --memory=X
flag), the memory.limit_in_bytes
parameter will still have a value, although of the magnitude of around 2^63 - 4096:
> cgget -nvr memory.limit_in_bytes /
9223372036854771712
Unless you want to start your JVM with a minimum heap space of about 8 EB, your entrypoint script should also consider this case:
MAX_RAM=$(cgget -nvr memory.limit_in_bytes /)
if [ $MAX_RAM -le 137438953472 ] ; then
JVM_MIN_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.2" | bc))
JVM_MAX_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.8" | bc))
else
JVM_MIN_HEAP=32G
JVM_MAX_HEAP=128G
fi
exec java "-Xms${JVM_MIN_HEAP}" "-Xmx${JVM_MAX_HEAP}" -jar my_jar.jar