6

我有一个基本的 java 映像,其中一些预定义的 java_opts 作为环境变量。如何在插件中使用它们?

                    <plugin>
                        <groupId>com.google.cloud.tools</groupId>
                        <artifactId>jib-maven-plugin</artifactId>
                        <version>1.8.0</version>
                        <configuration>
                            <from>
                                <image>${docker.registry}java:11</image>
                            </from>
                            <to>
                                <image>${docker.registry}portal-backend:${dockerfile.tag}</image>
                            </to>
                            <container>
                                <jvmFlags>
                                    # This will fail
                                    <jvmFlag>$JAVA_OPTS</jvmFlag>
                                </jvmFlags>
                            </container>
                        </configuration>
                    </plugin>
4

3 回答 3

8

(在我开始之前:即使$JAVA_OPTS在编译时运行 Maven 构建时扩展(显然它没有扩展),<jvmFlag>$JAVA_OPTS<jvmFlag>仍然会失败,因为$JAVA_OPTS包含多个 JVM 标志的整个字符串值将作为单个参数传递给java二进制。例如,-Xms1024m -Xmx2048m应该作为两个单独的标志传递。包括空格作为单个参数的整个字符串不是有效的 JVM 标志。)


如果可能,请定义基本图像JAVA_TOOL_OPTIONS(注意 not JAVA_TOOL_OPTSnor JAVA_OPTS)。大多数 JVM 都会尊重JAVA_TOOL_OPTIONS. 有关详细信息,请参阅https://stackoverflow.com/a/58715040/1701388。(另请注意,容器运行时(docker、Kubernetes 等)始终可以在运行时提供环境变量(和/或覆盖在构建时定义为容器配置的任何变量)。也就是说,您可以在运行时动态设置参数。)


另一种选择是定义自己<entrypoint>的使用外壳。(因此,您需要一个包含 shell 二进制文件(例如/bin/bash)的基本映像。请注意,Jib 3.0 之前的默认基本映像是Distroless并且不包含 shell 程序。OTOH,Jib 3.0+ 不使用 Distroless。)

在这种方法中,您需要知道正确的 Java 运行时类路径和要在 JVM 启动命令中使用的主类。为了解决这个问题,从 Jib >= 3.1 开始,Jib在构建的映像中创建了两个 JVM 参数文件;它们将分别保存构建图像中的类路径和主类。

知道入口点后,您可以编写一个 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>文件即可执行。这可能看起来不习惯;您通常会使脚本可执行并直接运行它。但这是完全有效的,在实际执行方面没有区别(只要 shebang/entrypoint.sh的相同#!/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>
于 2019-12-16T17:34:05.680 回答
1

我的解决方案是完全从 jib-maven-plugin 配置中删除 JVM 内存参数。相反,我为容器定义JAVA_TOOL_OPTIONS环境变量(例如:JAVA_TOOL_OPTIONS='-Xss=512k')(例如:在 docker-compose 配置文件中)。

请注意,此环境变量根本不需要在基础映像中定义。

于 2021-02-25T09:29:35.807 回答
0

变量定义如下

选项 1:Java 系统属性(VM 参数)

重要的是 -D 参数在您的 application.jar 之前,否则它们将无法识别。

java -jar -Dspring.profiles.active=prod application.jar

选项 2:程序参数

java -jar application.jar --spring.profiles.active=prod --spring.config.location=c:\config

POM 更改:使用 jib 作为 maven 插件时 - 更改 spring 配置文件位置的加载:然后 entryPoint 在容器内传递,但似乎 jib 插件没有选择它。因此,需要在 pom 中对 location 的参数访问进行以下更改:

<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>2.2.0</version>
    <configuration>
        <to>
            <image>image-url</image>
        </to>
        <container>
            <creationTime>${​​​​​​maven.build.timestamp}​​​​​​&lt;/creationTime>
            <mainClass>com.package.SpringBootMainClass</mainClass>
            <args>
                <arg>--spring.config.location=/demo/location/application.yml</arg>
            </args>
        </container>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
</plugin>

pom 中的 Jib-maven 插件如何传递参数,只是通过 pom 展示了一种方式,jib 不会从 spring 应用程序的入口点获取参数,这就是为什么考虑提供另一种方式的原因。如上答案没有。

于 2021-01-14T07:46:31.513 回答