使用 Podman for Windows 的 Quarkus Native

使用 Windows 工作站的开发人员可能会面临运行 Linux 原生工作流程的挑战。实现这一目标的一种方法是使用 Podman,这是一种容器引擎,提供运行 Linux 容器的命令行功能。Podman 支持以“rootful”和“rootless”两种模式运行容器,其中后者是默认模式,不需要提升的权限。在这篇博文中,我们将探讨如何在 Windows 上将 Podman 与 Quarkus Native 结合使用来构建和运行应用程序。
在 Windows 上安装 Podman
在我最近的经历中,我使用了两种设置:一种是在旧的基于 Xeon 的裸机台式机上运行的 Windows 10,另一种是在我的 CentOS 8 Stream Linux 笔记本电脑上运行的由 Qemu 驱动的 Windows 10 虚拟机。前者在使用 Podman for Windows 指南时没有任何问题,而后者则需要在 /etc/libvirt/qemu/win10.xml
中进行一些 手动调整 以允许嵌套虚拟化。不过,具体情况可能会因客户机 Windows 和虚拟机管理程序的版本而异。
除了命令行,还有完整的 Podman Desktop 体验,可在 https://desktop.podman.org.cn/ 上获得。安装程序会检查您的设置并指导您

Quarkus Native 构建器镜像
最新的 Quarkus 2 和 Quarkus 3 都会自动检测是否安装了 Podman 或 Docker,并使用它们来运行容器。
我们将使用一个为图片添加水印的 QuickStart 示例。该示例依赖于尚未移植到 Windows 原生运行的 Quarkus AWT 扩展,但我们使用 Windows 工作站来开发我们的 Java 代码,因此使用 Linux 容器进行原生构建非常适合我们。我们在 Windows 上使用 cmder 终端,但普通的 cmd 提示符也可以。
C:\tmp
λ git clone https://github.com/quarkusio/quarkus-quickstarts.git
λ cd quarkus-quickstarts\awt-graphics-rest-quickstart
λ git checkout development
根据您的 Podman 安装情况,您可能还需要运行 podman machine start
。 Podman 输出。
C:\tmp\quarkus-quickstarts\awt-graphics-rest-quickstart (development -> origin) λ mvnw package -Dnative -Dquarkus.native.container-build=true -Dquarkus.platform.version=3.1.2.Final
我们可以在日志中看到 Quarkus 检测到我们有 podman.exe
可用,并使用了 Mandrel 构建器镜像进行构建,即我们的 Java 字节码以及各种资源和属性在 Linux 容器中可用,其中 native-image
工具创建了一个 ELF64 Linux 可执行文件。我们现在可以在 target
目录中看到该文件了。
λ file target\awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-runner
target\awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-runner: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0,
BuildID[sha1]=20820fdafc19e803147d91fbba6823ad45024041, not stripped
我们无法在此 Windows 工作站上运行该可执行文件,但我们可以立即使用另一个 Linux 镜像在其容器中运行它。
λ podman build -f src/main/docker/Dockerfile.native -t quarkus/awt-graphics-rest .
我们来运行它
C:\tmp\quarkus-quickstarts\awt-graphics-rest-quickstart (development -> origin)
λ podman run -i --rm -p 8080:8080 quarkus/awt-graphics-rest
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-06-22 15:53:03,890 INFO [io.quarkus] (main) awt-graphics-rest-quickstart 1.0.0-SNAPSHOT native (powered by Quarkus 3.1.2.Final) started in 0.169s. Listening on: http://0.0.0.0:8080
2023-06-22 15:53:03,890 INFO [io.quarkus] (main) Profile prod activated.
2023-06-22 15:53:03,890 INFO [io.quarkus] (main) Installed features: [awt, cdi, resteasy, resteasy-multipart, smallrye-context-propagation, vertx]
现在我们可以让应用程序为我们添加图片水印。首先,我们需要一些图片来添加水印

C:\tmp
λ curl https://quarkus.net.cn/assets/images/posts/podman-for-windows/orig-790x230.png --output C:/tmp/example.png
接下来,我们使用我们本地运行的容器来为它添加水印
C:\tmp
λ curl -F "image=@C:/tmp/example.png" https://:8080/watermark --output C:/tmp/result.png
并查看结果,左上角是 Mandrel 字样,右下角是 Quarkus 标志。
C:\tmp
λ mspaint.exe C:/tmp/result.png

在您的测试流程中使用 Linux 容器
您还可以使用 Podman 在 Linux 容器中运行您的测试。例如,您可以利用 quarkus-container-image-docker
扩展。将其添加到 pom.xml
文件中
...
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-container-image-docker</artifactId>
+ </dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
...
我们来运行它
λ mvnw verify -Ddocker -Dnative -Dquarkus.native.container-build=true -Dquarkus.container-image.build=true -Dquarkus.platform.version=3.1.2.Final
这是 完整输出。
浏览日志,我们可以看到基于 JVM 的测试首先通过了
...
[INFO] Running org.acme.awt.rest.ImageResourceTest
INFO [io.quarkus] (main) awt-graphics-rest-quickstart 1.0.0-SNAPSHOT on JVM
...
然后使用 Linux 构建器镜像来构建 Linux 可执行文件
...
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildContainerRunner] Using podman to run the native image builder
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildContainerRunner] Checking image status quay.io/quarkus/ubi-quarkus-mandrel-builder-image:22.3-java17
...
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] podman run...
...
接下来,我们可以看到集成测试套件决定构建一个 Linux 容器镜像,并将我们新构建的可执行文件放入其中。
...
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Starting (local) container image build for native binary using docker.
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Executing the following command to build docker image: 'podman build -f C:\tmp\quarkus-quickstarts\awt-graphics-rest-quickstart\src\main\docker\Dockerfile.native -t karm/awt-graphics-rest-quickstart:1.0.0-SNAPSHOT C:\tmp\quarkus-quickstarts\awt-graphics-rest-quickstart'
...
最后,集成测试套件在容器中启动应用程序,并针对它运行测试。
...
[INFO] Running org.acme.awt.rest.ImageResourceIT
INFO [io.qua.tes.com.DefaultDockerContainerLauncher] (main) Executing "podman run...
...
我们可以查看保留的 target/quarkus.log
文件,确认应用程序确实在 Linux 容器中作为原生可执行文件运行。
λ type target\quarkus.log
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-06-22 21:41:27,637 INFO [io.quarkus] (main) awt-graphics-rest-quickstart 1.0.0-SNAPSHOT native (powered by Quarkus 3.1.2.Final) started in 0.062s. Listening on: http://0.0.0.0:8081
2023-06-22 21:41:27,637 INFO [io.quarkus] (main) Profile prod activated.
2023-06-22 21:41:27,637 INFO [io.quarkus] (main) Installed features: [awt, cdi, resteasy, resteasy-multipart, smallrye-context-propagation, vertx]
2023-06-22 21:41:30,264 INFO [io.quarkus] (Shutdown thread) awt-graphics-rest-quickstart stopped in 0.002s
通过这种方式,我们可以在保留 Windows 开发环境的同时,在 Linux 容器中执行我们的测试应用程序。
故障排除
-
文件权限: Linux 可执行文件可能缺少可执行标志,因此您可能需要在 Dockerfile 中设置它,就像我们在 Quickstart AWT 示例中所做的那样,即
RUN chmod "ugo+x" /work/application
。 -
Podman machine 必须已初始化: 如果出现问题,管理员可以通过删除 machine(提供 podman 服务的 Linux VM)来修复它,例如
podman machine rm "podman-machine-default"
然后podman machine init
。 -
目录或文件访问: 在构建更多服务或更复杂的模块化项目时,可能会遇到“进程无法访问该文件,因为它正被另一个进程使用”的错误。调试这种情况最简单的方法是使用 Sysinternals 的 Handle 工具。
请注意,上述任何情况本身都不是 Quarkus 特有的。
结论
Podman 完全能够运行您的 Linux 容器在 Windows 上,无论是测试应用程序还是数据库。绝对值得一试。
您对这篇博文有任何疑问吗?欢迎随时在 Zulip 聊天、Stack Overflow 或 GitHub 上联系我们。