调试使用 quarkus-container-image-jib 打包的 Quarkus 应用程序

我想在我们的开发、登台和生产环境中运行相同的图像。对于我们的开发环境,我希望能够连接调试器。

我像这样为我们的 Quarkus 应用程序构建图像(mvn 包):

<dependencies>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-container-image-jib</artifactId>
    </dependency>
    ...
</dependencies

<properties>
    <quarkus.container-image.build>true</quarkus.container-image.build>
    <quarkus.jib.ports>8080,5005</quarkus.jib.ports>
    <quarkus.container-image.image>...</quarkus.container-image.image>
    ...
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-maven-plugin</artifactId>
            <version>1.12.1.Final</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build</goal>
                    </goals>
                    <phase>package</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

是否可以在调试模式下启动应用程序,同时使用 prod 配置文件运行?通过环境变量将 JAVA_OPTIONS=-Ddebug=true 传递给容器会导致 Exception in thread "main" java.nio.file.NoSuchFileException: /work/lib/deployment/deployment-class-path.dat

如果不是,那么完成这种设置的适当方法是什么?

stack overflow Debug Quarkus app packaged with quarkus-container-image-jib
原文答案
author avatar

接受的答案

有几种方法可以做到这一点,但它们都依赖于这样一个事实,即在 Quarkus 中,您可以控制 Jib 为容器镜像使用任何您想要的启动脚本。默认情况下,容器映像是使用最小的 java -jar ... 样式 ENTRYPOINT 创建的,但可以使用 quarkus.jib.jvm-entrypoint 进行更改。

如果您使用默认的基本图像,它已经包含一个提供大量选项的 run-java.sh 脚本(请参阅 https://hub.docker.com/r/fabric8/java-alpine-openjdk11-jre#startup-script-run-javash ),那么您可以通过在 application.properties 中设置以下内容来完成您想要完成的工作:

quarkus.jib.jvm-entrypoint=/deployments/run-java.sh
quarkus.jib.environment-variables."JAVA_APP_DIR"=/work # this is needed so the script knows where the Quarkus jar is

然后使用以下命令启动应用程序:

docker run --rm -p 8080:8080 -p 5005:5005 -e JAVA_DEBUG=true gandrian/getting-started:1.0.0-SNAPSHOT

现在应用程序将打开调试端口(但不会挂起),您可以使用调试器连接到它


答案:

作者头像

可以使同一个 Quarkus 镜像在您的 Kubernetes 部署中打开一个调试端口,即不重建镜像仅用于调试。将 JIB 与 Red Hat UBI 基础映像一起使用时,例如 quarkus.jib.base-jvm-image=registry.access.redhat.com/ubi8/openjdk-11-runtime:1.14 ,这通过覆盖部署 K8S 描述符中的容器命令来实现,如下所示:

      containers:
      - name: your-app
        image: your-app-image
        command: ["java"]
        args: ["-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", -Djava.util.logging.manager=org.jboss.logmanager.LogManager", "-jar", "quarkus-run.jar"]

这会覆盖 Docker 镜像的入口点,它看起来像这样(从 docker inspect 收集):

            "Entrypoint": [
                "java",
                "-Djava.util.logging.manager=org.jboss.logmanager.LogManager",
                "-jar",
                "quarkus-run.jar"
            ],

如果入口点相同,这可能也适用于除 JIB 之外的其他基础映像和容器构建器。作为记录,带有 JIB 的 Quarkus 图像入口点似乎是在此处以编程方式确定的: https://github.com/quarkusio/quarkus/blob/c28a72b63104d8856fac1481b107c9f9ff3e7f1a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java#L390