无法使用 Jib 编辑 1

问题描述

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

More 除了关注 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 Boot 可执行文件。我不关心睡眠,它是 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 目录。

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

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

问题

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

编辑 1

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

解决方法

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

Jib 决定如何处理战争项目

Jib 还容器化 WAR 项目。如果 Gradle 项目使用 WAR Plugin,Jib 默认会使用 jetty 作为基础镜像来部署项目 WAR。除了使用 WAR 插件让 Jib 构建 WAR 镜像外,无需额外配置。

这可能就是 JHipster 需要一个 -Pwar 启动属性来公开战争任务的原因,以便您可以构建 Spring Boot jar 的容器化版本,或者生成结果的 web-server-ed 容器战争文件。

为我没有阅读文档而感到羞耻

,

对于那些可能只想开始在 Spring Boot 中使用 Jib 但由于任何原因遇到问题的人:

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

  1. 例如,使用 Spring Initializr 创建一个 Spring Boot 应用程序。无论是 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