无法使用 Jib 打包我的 Spring 启动应用程序

Can't package my Spring Boot application with Jib

我想使用带有 Gradle 的 Jib 将我的 Spring 引导应用程序打包为 Docker 容器。

更多 除了遵循 Jib's readme,我还从一个简单的 JHipster 项目中复制了一个示例。你猜怎么着?没用。

好的,这是代码。

JHipster 生成器创建一个专用的 gradle/docker.gradle 文件,该文件从主 Gradle 构建文件中应用,并且正在导入 Jib 插件

所以我复制了JH jib文件开始

我的gradle/jib.gradle

jib {
    from {
//        image = "adoptopenjdk:8-jre"
        image = "adoptopenjdk:11-jre-hotspot"
    }
    to {
        image = "myapp:latest"
    }
    container {
        entrypoint = ["bash", "-c", "/entrypoint.sh"]
        ports = ["8080"]
        environment = [
            SPRING_OUTPUT_ANSI_ENABLED: "ALWAYS",
            SPRBOOT_SLEEP: "0"
        ]
        creationTime = "USE_CURRENT_TIMESTAMP"
    }
    extraDirectories {
      paths = file("src/main/jib")
      permissions = ["/entrypoint.sh": "755"]
    }
}

评论部分是因为我想使用 JDK8,但我正在尝试使用 JHipster 所做的。

其次,我根据JH 的存储库复制了自己的entrypoint.sh。这里是src/main/jib/entrypoint.sh

#!/bin/sh

echo "The application will start in ${SPRBOOT_SLEEP}s..." && sleep "${SPRBOOT_SLEEP}" # Author's note: it's pointless
exec java "${JAVA_OPTS}" -noverify \
  -XX:+AlwaysPreTouch \
  -Djava.security.egd=file:/dev/./urandom \
  -cp /app/resources/:/app/classes/:/app/libs/* \
  "com.acme.MyApplication" "$@"

当然,我必须将 jib 插件 3.0.0 添加到我的 Gradle 文件,应用 jib.gradle 脚本

plugins {
    id 'org.springframework.boot' version '2.4.2'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
    id 'war'
    id "com.google.cloud.tools.jib" version '3.0.0'
    id 'org.unbroken-dome.test-sets' version '3.0.1'
    id 'org.flywaydb.flyway' version '7.5.4' apply false
    id 'com.telenia.gradle.MybatisGenerator' version '2.1.5'
    id 'net.ltgt.apt-eclipse' version '0.21' apply false
}

apply from: 'gradle/jib.gradle'

说明时间

现在我希望 gradle jibDockerBuild 使用我的应用程序文件在 /app 下创建一个容器,并使用入口点启动 Spring 引导可执行文件。 sleep我不管,是0,被JH继承了

当然,当我从 JHipster 项目构建 Docker 图像时,它就像一个魅力。当我构建自己的容器时,运行 它失败并出现经典的 Unable to locate main class 错误

The application will start in 0s...

Error: Could not find or load main class

Caused by: java.lang.ClassNotFoundException:

我试图bash进入容器,但根本没有/app目录。 JHipster构建的容器下有一个/app目录

在撰写本文 post 时,我尝试检查两张图片 ,我发现了一些差异。 JHipster 在 /app 下部署文件,而我的 Gradle 脚本在 /var/lib/jetty/webapps/ROOT 下部署 jar。我的应用程序始终启用 war 插件,而 JHipster 仅在设置 -Pwar 变量时才启用插件。

我不关心在图像中使用 war 或嵌入式服务器,只要结果是生产级的。我仍然需要能够构建一个 war 文件。

问题

如何使用 Jib 将现有的基于 Gradle 的 Spring 引导项目正确配置为构建为 Docker 容器?我的代码有什么问题,因为我优先考虑 JHipster 中基于 Spring Boot 的现有代码?

编辑 1

:在 JHipster 项目中,gradle -Pwar jibDockerBuild 将文件部署在容器内的 /jetty/webapps 下,当我启动应用程序时,我得到了魔法错误 Could not find or load main class

我的错误是没有完整阅读 Jib 文档。

Jib 决定在 War 个项目上做什么

Jib also containerizes WAR projects. If the Gradle project uses the WAR Plugin, Jib will by default use jetty as a base image to deploy the project WAR. No extra configuration is necessary other than using the WAR Plugin to make Jib build WAR images.

这可能是 JHipster 要求 -Pwar 启动 属性 以公开 war 任务的原因,以便您可以构建 Spring 的容器化版本引导 jar,或生成的 war 文件的 web-server-ed 容器。

没看文档真可惜

对于那些可能只想开始将 Jib 与 Spring 引导一起使用但由于任何原因遇到问题的人:

大多数时候,Jib 应该与 Spring Boot 开箱即用。这是用于演示的最小设置:

  1. 创建一个 Spring 启动应用程序,例如,使用 Spring Initializr。不管是 Maven 还是 Gradle 项目:
    $ curl https://start.spring.io/starter.tgz \
        -d type=gradle-project \
        -d dependencies=web \
        -d baseDir=demo | tar -xzvf -
    
  2. 打开 build.gradle 并应用 Jib 插件。
     plugins {
         id 'org.springframework.boot' version '2.4.5'
         id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    +    id 'com.google.cloud.tools.jib' version '3.0.0'
         id 'java'
     }
    
  3. 使用 Jib 进行容器化。
    $ ./gradlew jibDockerBuild
    
  4. 运行 图片。 (该应用程序可在 localhost:8080 访问。)
    $ docker run --rm -p8080:8080 demo:0.0.1-SNAPSHOT
    

这是一个最小的设置,但您肯定希望进一步自定义 Jib 配置。

最后,尽可能选择 <packaging>jar 而不是 war