Docker 使用cgroups 来实现资源限制。在容器内部,您可以使用cgget 实用程序来打印各种子系统(在本例中为memory 子系统)的参数。
例如,考虑一个内存限制为 64G 的容器(毕竟是 Java):
> docker run --memory=64G
在容器内,然后使用cgget读取memory.limit_in_bytes参数的当前值:
> cgget -nvr memory.limit_in_bytes /
68719476736
请注意,您可能必须首先通过容器映像的包管理器安装 cgget 二进制文件。在 Ubuntu 上,您需要 cgroup-bin 包。
然后您可以使用此值来动态计算您的 JVM 参数(仅作为示例,根据您自己的需要进行调整):
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
重要提示:在没有内存限制的情况下运行(即没有--memory=X 标志),memory.limit_in_bytes 参数仍然有一个值,尽管大小在 2^63 - 4096 左右:
> cgget -nvr memory.limit_in_bytes /
9223372036854771712
除非您想以大约 8 EB 的最小堆空间启动 JVM,否则您的入口点脚本也应该考虑这种情况:
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