【问题标题】:Build Spring Boot fat JAR using JIB使用 JIB 构建 Spring Boot fat JAR
【发布时间】:2021-02-27 03:31:55
【问题描述】:

我有一个多模块项目,我使用 Jib 构建 Spring Boot 应用程序。我知道将胖 JAR 放入容器会阻止有效地构建映像 (see),但需要将一个特定模块打包到胖 JAR 文件中。由于我想为整个多模块项目保留相同的构建工具,是否可以使用 Jib 打包 fat jar?

我已经尝试过repackage 目标

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.3.5.RELEASE</version>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

即打包应用如

app
├── classpath
│   └── import-metadata-service-0.0.1-SNAPSHOT.original.jar
└── libs
    ├── HdrHistogram-2.1.12.jar
    ├── LatencyUtils-2.0.3.jar
    ├── apache-jena-libs-3.13.0.pom 
    ...

【问题讨论】:

  • 有一种 hacky 方法可以实现你想要的。但在此之前,我们想了解您是否在普通的瘦 JAR 容器化(如图中的 .original.jar 所示)和 Spring Boot 胖 JAR 之间看到了不同的应用程序行为?如果是这样,您可以在 Jib 回购中提出问题吗?不能拿原来的瘦JAR是什么问题?
  • fatjar 也需要复制到另一个镜像中。保留这个包装,我不必更改将 fatjat 复制到的图像。我没有考虑为我的非常具体的用例打开一个问题,因为它根本不是 jib 的范围。我正在考虑使用另一个构建工具,因为即使我可以设法将应用程序打包为 fatjar,我当然也必须修改另一个图像,因为我无法直接使用 java -jar (@987654322 @),不是吗?
  • 好吧,我不会质疑你为什么要这个。有几种不同的创造性(hacky)方法可以实现这一点,但也许最简单的一种是使用&lt;extraDirectories&gt; 功能将您的胖JAR 复制到您想要的任何地方,将&lt;container&gt;&lt;entrypoint&gt; 设置为执行java -jar ...(您想要的任何命令) 和 remove the entire /app/* 使用 Jib Layer-Filter extension
  • 仅供参考,我们目前正致力于发布一个名为“Jib CLI”的 CLI 工具,Jib CLI 可能更适合您的工作流程。敬请期待。

标签: jib maven-jib


【解决方案1】:

如果有人对此感到困惑:我有一个类似的用例,我想利用 jib(Dockerfile-less + 可以在没有 docker daemon 的情况下使用),但由于其他原因,我目前无法拒绝使用 fat jars。

基于 Chanseok cmets(根据问题),我想出了以下内容:

  • 删除由 jib 添加的任何层
  • 将fatjar(默认在target/${build.finalName}.jar)添加到自己的层中
  • 覆盖入口点以执行“java -jar ...”而不是指向您的 Main 的常规入口点
  • Jib 被显式调用并且不绑定到生命周期(至少在我的示例中),因此必须使用以下 mvn package jib:dockerBuild(或 ... jib:build 用于无 docker-daemon-less 构建)显式调用它
  • 使用dive,您会看到只添加了一层并且它相当大(== 胖罐)

来源:https://gitter.im/google/jib?at=5fad68c5d37a1a13d6a12174 + https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#extradirectories-object

该示例至少适用于 spring boot 2.4.X

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>com.google.cloud.tools</groupId>
            <artifactId>jib-maven-plugin</artifactId>
            <version>3.0.0</version>
            <dependencies>
                <dependency>
                    <groupId>com.google.cloud.tools</groupId>
                    <artifactId>jib-layer-filter-extension-maven</artifactId>
                    <version>0.2.0</version>
                </dependency>
            </dependencies>
            <configuration>
                <container>
                    <entrypoint>java,-jar,/app/${project.build.finalName}.jar</entrypoint>
                </container>
                <extraDirectories>
                    <paths>
                        <path>
                            <from>target/</from>
                            <includes>*.jar</includes>
                            <into>/app</into>
                        </path>
                    </paths>
                </extraDirectories>
                <pluginExtensions>
                    <pluginExtension>
                        <implementation>com.google.cloud.tools.jib.maven.extension.layerfilter.JibLayerFilterExtension</implementation>
                        <configuration implementation="com.google.cloud.tools.jib.maven.extension.layerfilter.Configuration">
                            <filters>
                                <filter>
                                    <!-- exclude all jib layers, which is basically anything in /app -->
                                    <glob>/app/**</glob>
                                </filter>
                                <filter>
                                    <!-- this is our fat jar, this should be kept by adding it into its own layer -->
                                    <glob>/app/${project.build.finalName}.jar</glob>
                                    <toLayer>jib-custom-fatJar</toLayer>
                                </filter>
                            </filters>
                        </configuration>
                    </pluginExtension>
                </pluginExtensions>
            </configuration>
        </plugin>
    </plugins>
</build>

【讨论】:

    【解决方案2】:

    是的,可以使用 Jib 将胖 jar 放在容器图像上。请使用 Jib 的“containerizingMode”配置选项:

    <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>jib-maven-plugin</artifactId>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>build</goal>
                </goals>
            </execution>
       </executions>
        <configuration>
            <containerizingMode>packaged<containerizingMode>                
        </configuration>
    </plugin>
    

    全套Jib配置选项请参考https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#extended-usage

    【讨论】:

    • 我不确定依赖项是否使用此选项打包在 JAR 文件中。我需要验证,但我记得测试过。另外,如果您可以这样做,我非常有信心@ChanseokOh 会给我这个答案。我可以看到他为 Jib github 做出了很多贡献。我会告诉你的
    • 依赖项肯定打包在 JAR 文件中。您可以通过提取构建的 JAR 输出来验证这一点——您将在 BOOT-INF/lib 下找到它们。如果你找到了,请告诉我。
    猜你喜欢
    • 2016-02-08
    • 2021-08-01
    • 1970-01-01
    • 2021-06-03
    • 2020-09-07
    • 2017-06-18
    • 2015-04-16
    • 2017-08-16
    • 1970-01-01
    相关资源
    最近更新 更多