(在我开始之前:即使 $JAVA_OPTS 在编译时运行 Maven 构建时被扩展(显然它没有被扩展),<jvmFlag>$JAVA_OPTS<jvmFlag> 仍然会失败,因为 $JAVA_OPTS 的整个字符串值包含多个 JVM 标志将作为 single 参数传递给 java 二进制文件。例如,-Xms1024m -Xmx2048m 应作为两个单独的标志传递。包括空格作为单个参数的整个字符串不是一个有效的 JVM 标志。)
如果可能,让基本映像定义JAVA_TOOL_OPTIONS(注意不是JAVA_TOOL_OPTS 也不是JAVA_OPTS)。大多数 JVM 都会使用 JAVA_TOOL_OPTIONS。有关详细信息,请参阅https://stackoverflow.com/a/58715040/1701388。 (另请注意,容器运行时(docker、Kubernetes 等)始终可以在运行时提供环境变量(和/或覆盖在构建时定义为容器配置的任何变量)。也就是说,您可以 dynamically set arguments at runtime。)
另一种选择是定义您自己的<entrypoint> 以使用shell。 (因此,您需要一个包含 shell 二进制文件的基本映像(例如 /bin/bash)。请注意,Jib 3.0 之前的默认基本映像是 Distroless,并且不包含 shell 程序。OTOH,Jib 3.0+ doesn't use Distroless。)
在此方法中,您需要知道正确的 Java 运行时类路径和要在 JVM 启动命令中使用的主类。为了解决这个问题,从 Jib >= 3.1 开始,Jib 在构建的图像中创建 two JVM argument files;它们将分别保存构建图像中的类路径和主类。
知道了入口点,就可以写一个shell脚本(my-entrypoint.sh):
#!/bin/sh
# Assumes `java` is on PATH in the base image.
exec java $JAVA_OPTS \
-cp $( cat /app/jib-classpath-file ) \
$( cat /app/jib-main-class-file )
或者,如果您使用的是 Java 9+,则可以利用 @-argument 文件:
exec java $JAVA_OPTS -cp @/app/jib-classpath-file @/app/jib-main-class-file
将my-entrypoint.sh 放在<project root>/src/main/jib 下。这是 Jib 的 <extraDirectories> 功能的默认目录,Jib 会将 src/main/jib/my-entrypoint.sh 放置在容器镜像的根目录中。然后将默认的<entrypoint>设置为这个脚本:
<container>
<!-- Assumes you have /bin/sh as specified at the top of /my-entrypoint.sh. -->
<entrypoint>/my-entrypoint.sh</entrypoint>
</container>
<!-- You also need to make the script executable. -->
<extraDirectories>
<permissions>
<permission>
<file>/my-entrypoint.sh</file>
<mode>755</mode>
</permission>
</permissions>
</extraDirectories>
或者,如果您如下调用/bin/sh,则不必配置<extraDirectories> 以使文件可执行。这可能看起来不习惯;您通常会使脚本可执行并直接运行它。但这是完全有效的,在实际执行上并没有什么区别(只要/entrypoint.sh的shebang和#!/bin/sh一样)。
<container>
<entrypoint>
<arg>/bin/sh</arg>
<arg>/my-entrypoint.sh</arg>
</entrypoint>
</container>
也可以在不创建脚本的情况下执行此操作(基本上将整个脚本嵌入pom.xml 并将其传递给shell 程序)。这种情况下不需要配置<extraDirectories>。
<container>
<entrypoint>
<arg>/bin/sh</arg>
<arg>-c</arg>
<arg>exec java $JAVA_OPTS -cp $( cat /app/jib-classpath-file ) $( cat /app/jib-main-class-file )</arg>
</entrypoint>
</container>