The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

构建一个原生可执行文件

本指南包括:

  • 将应用程序编译为原生可执行文件

  • 将原生可执行文件打包到一个容器中

  • 调试原生可执行文件

本指南将 入门指南中开发的应用程序作为输入。

GraalVM

构建一个原生可执行文件需要使用GraalVM的发行版。有三个发行版:Oracle GraalVM社区版(CE)、Oracle GraalVM企业版(EE)和Mandrel。Oracle和Mandrel发行版之间的区别如下:

  • Mandrel是Oracle GraalVM CE的一个下游发行版。Mandrel的主要目标是提供一种方法来构建专门为支持Quarkus而设计的原生可执行文件。

  • Mandrel版本的代码库来自于上游的Oracle GraalVM CE代码库,只做了一些小的改动,但也有一些重要的对于Quarkus本地应用程序来说是没有必要的排除项。它们支持与Oracle GraalVM CE相同的构建原生可执行文件的能力,在功能上没有重大变化。值得注意的是,它们不包括对多语言编程的支持。之所以排除这些功能,是为了给大多数Quarkus用户提供更好的支持水平。与Oracle GraalVM CE/EE相比,这些不包括的内容也意味着Mandrel发布的软件包大小大大减小。

  • Mandrel is built slightly differently to Oracle GraalVM CE, using the standard OpenJDK project. This means that it does not profit from a few small enhancements that Oracle have added to the version of OpenJDK used to build their own GraalVM downloads. These enhancements are omitted because upstream OpenJDK does not manage them, and cannot vouch for. This is particularly important when it comes to conformance and security.

  • Mandrel被推荐用于构建针对Linux容器化环境的原生可执行文件。这意味着,我们鼓励Mandrel用户使用容器来构建他们的原生可执行文件。如果你要为macOS构建本地可执行文件,你应该考虑使用Oracle GraalVM,因为Mandrel目前不针对这个平台。直接在裸机Linux或Windows上构建原生可执行文件是可能的,详情可参见 Mandrel READMEMandrel发行版

先决条件

要完成这个指南,你需要:

  • 大概15分钟

  • 编辑器

  • 安装JDK 11以上版本并正确配置了 JAVA_HOME

  • Apache Maven 3.8.1+

  • A working container runtime (Docker or Podman)

  • 如果你愿意的话,还可以选择使用Quarkus CLI

  • 可以安装Mandrel或者GraalVM,并正确配置

  • 一个 C语言工作开发环境

  • 入门指南 中开发的应用程序代码。

支持在C语言中进行原生编译

拥有一个C语言工作开发者环境意味着什么?

  • 在Linux上,你将需要GCC,以及glibc和zlib头文件。常见发行版的例子:

    # dnf (rpm-based)
    sudo dnf install gcc glibc-devel zlib-devel libstdc++-static
    # Debian-based distributions:
    sudo apt-get install build-essential libz-dev zlib1g-dev
  • XCode在macOS上提供了必要的依赖性:

    xcode-select --install
  • 在Windows上,你将需要安装 Visual Studio 2017 Visual C++构建工具

配置GraalVM

如果你无法安装GraalVM,你可以使用多阶段Docker构建在嵌入GraalVM的Docker容器内运行Maven。本指南最后有关于如何操作的解释。

版本 22.1 是必需的。使用社区版就可以了。

  1. 如果你还没有安装 GraalVM。那么你有几个选择:

  2. 配置运行环境。将 GRAALVM_HOME 环境变量设置为GraalVM的安装目录,例如:

    export GRAALVM_HOME=$HOME/Development/graalvm/

    在macOS上(Mandrel不支持),将该变量指向 Home 子目录:

    export GRAALVM_HOME=$HOME/Development/graalvm/Contents/Home/

    在Windows上,您将不得不通过控制面板来设置你的环境变量。

    通过scoop安装将为你做到这一点。

  3. (仅适用于Oracle GraalVM CE/EE)使用 gu install 安装 native-image 工具:

    ${GRAALVM_HOME}/bin/gu install native-image

    GraalVM以前的一些版本默认包括 native-image 工具。现在已经不是这样了,它必须在安装完GraalVM本身后作为第二步来安装。注意:一个已知的问题 在MacOS Catalina上使用GraalVM

  4. (可选)将 JAVA_HOME 环境变量设置为GraalVM的安装目录。

    export JAVA_HOME=${GRAALVM_HOME}
  5. (可选)将GraalVM bin 目录添加到路径中

    export PATH=${GRAALVM_HOME}/bin:$PATH
在MacOS Catalina上使用GraalVM的问题

GraalVM的二进制文件(尚未)对macOS Catalina进行认证,正如这个 GralVM问题中所报告的那样。这意味着您在使用 gu 时可能会看到以下错误:

“gu” cannot be opened because the developer cannot be verified

使用以下命令递归删除GraalVM安装目录上的 com.apple.quarantine 扩展属性,作为一种解决方法:

xattr -r -d com.apple.quarantine ${GRAALVM_HOME}/../..

解决方案

我们建议您按照下面几节的说明,一步一步地打包应用。不过您还可以直接进入完成的例子。

克隆 Git 仓库:git clone https://github.com/quarkusio/quarkus-quickstarts.git,或者下载一个 存档

该解决方案位于 getting-started 目录中。

制作一个原生可执行文件

我们应用程序的原生可执行文件将包含应用程序代码、所需的库、Java API和一个缩小版的虚拟机。较小的虚拟机基础提高了应用程序的启动时间和最小的磁盘占用。

创建原生可执行文件

如果你已经从前面的教程中生成了应用程序,你可以在 pom.xml ,找到以下 profile

<profiles>
    <profile>
        <id>native</id>
        <properties>
            <quarkus.package.type>native</quarkus.package.type>
        </properties>
    </profile>
</profiles>

你可以使用 <quarkus.native.additional-build-args> 属性为 native-image 命令提供自定义选项。多个选项可以用逗号隔开。

另一种做法是在你的 application.properties ,填写 quarkus.native.additional-build-args 配置属性。

你可以在下面的 [configuration-reference] 部分找到关于如何配置原生镜像构建过程的更多信息。

我们使用profile是因为,你很快就会看到,打包原生可执行文件需要 few 分钟。你可以在命令行中把 -Dquarkus.package.type=native 作为一个属性,但是最好是使用一个profile,因为这可以使原生镜像测试也被运行。

使用以下方法创建一个原生可执行文件:

CLI
quarkus build --native
Maven
./mvnw package -Dnative
Gradle
./gradlew build -Dquarkus.package.type=native
在Windows上打包的问题

在打包之前,必须首先初始化 Microsoft Native Tools for Visual Studio。你可以通过启动与Visual Studio Build Tools 一起安装的 x64 Native Tools Command Prompt 来做到这一点。在 x64 Native Tools Command Prompt ,你可以导航到你的项目文件夹并运行 mvnw package -Pnative

另一个解决方案是写一个脚本来为您做这件事:

cmd /c 'call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && mvn package -Pnative'

除了常规文件外,该构建还产生了 target/getting-started-1.0.0-SNAPSHOT-runner 。你可以用以下方式运行它: ./target/getting-started-1.0.0-SNAPSHOT-runner

Java预览功能

依赖于预览功能的Java代码需要特别注意。为了产生一个原生可执行文件,这意味着需要将 --enable-preview 标志传递给底层的原生镜像调用。你可以这样做,用 -J 作为标志的前缀,并将其作为额外的原生构建参数传递:-Dquarkus.native.additional-build-args=-J—​enable-preview

Build fully static native executables

Fully static native executables support is experimental.

On Linux it’s possible to package a native executable that doesn’t depend on any system shared library. There are some system requirements to be fulfilled and additional build arguments to be used along with the native-image invocation, a minimum is -Dquarkus.native.additional-build-args="--static","--libc=musl".

Compiling fully static binaries is done by statically linking musl instead of glibc and should not be used in production without rigorous testing.

测试原生可执行文件

Producing a native executable can lead to a few issues, and so it’s also a good idea to run some tests against the application running in the native file. The reasoning is explained in the Testing Guide.

要看到 GreetingResourceIT 面向原生可执行文件运行,使用 ./mvnw verify -Pnative

$ ./mvnw verify -Pnative
...
[getting-started-1.0.0-SNAPSHOT-runner:18820]     universe:     587.26 ms
[getting-started-1.0.0-SNAPSHOT-runner:18820]      (parse):   2,247.59 ms
[getting-started-1.0.0-SNAPSHOT-runner:18820]     (inline):   1,985.70 ms
[getting-started-1.0.0-SNAPSHOT-runner:18820]    (compile):  14,922.77 ms
[getting-started-1.0.0-SNAPSHOT-runner:18820]      compile:  20,361.28 ms
[getting-started-1.0.0-SNAPSHOT-runner:18820]        image:   2,228.30 ms
[getting-started-1.0.0-SNAPSHOT-runner:18820]        write:     364.35 ms
[getting-started-1.0.0-SNAPSHOT-runner:18820]      [total]:  52,777.76 ms
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.1:integration-test (default) @ getting-started ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.acme.quickstart.GreetingResourceIT
Executing [/data/home/gsmet/git/quarkus-quickstarts/getting-started/target/getting-started-1.0.0-SNAPSHOT-runner, -Dquarkus.http.port=8081, -Dtest.url=http://localhost:8081, -Dquarkus.log.file.path=build/quarkus.log]
2019-04-15 11:33:20,348 INFO  [io.quarkus] (main) Quarkus 999-SNAPSHOT started in 0.002s. Listening on: http://[::]:8081
2019-04-15 11:33:20,348 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy-reactive]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.387 s - in org.acme.quickstart.GreetingResourceIT
...

默认情况下,Quarkus会等待60秒的时间来启动原生镜像,然后本地测试自动失败。这个持续时间可以使用 quarkus.test.wait-time 系统属性来改变。例如,要增加持续时间到300秒,使用: ./mvnw verify -Pnative -Dquarkus.test.wait-time=300

这个过程以前是用 @NativeImageTest 注释来完成的。 @NativeImageTest 正考虑被废弃掉,而采用 @QuarkusIntegrationTest ,它提供了 @NativeImageTest 的测试能力的超集。关于 @QuarkusIntegrationTest 的更多信息可以在 测试指南 中找到。

配置文件

By default, integration tests both build and run the native executable using the prod profile.

可以在可执行文件 runs 测试期间覆盖配置文件的 quarkus.test.native-image-profile 属性。添加到 application.properties 或将其附加到命令行: ./mvnw verify -Pnative -Dquarkus.test.native-image-profile=test。您的 %test. 前缀属性将在测试运行时使用。

可以使用 quarkus-profile=test 属性覆盖可执行文件 builtruns 的配置文件。例如 ./mvnw clean verify -Pnative -Dquarkus-profile=test。如果要处理特定于测试的资源,例如将测试数据导入数据库,那么这可能会很方便。

在前面提到的 `application.properties` 例子中。在JVM模式测试运行期间和原生模式测试运行期间,Hibernate ORM管理的数据库将填充测试数据。生产可执行文件将只包含 `version.txt` 资源,没有多余的测试数据。

[WARNING]
====
使用 `-Dquarkus-profile=test` 构建的可执行文件不适合生产部署。它包含您的测试资源文件和设置。一旦测试完成,就必须使用默认的 `prod` 配置文件再次构建可执行文件。
====

=== Java预览功能

[[graal-test-preview]]
[NOTE]
.Java预览功能
====
依赖于预览功能的Java代码需要特别注意。为了测试一个原生可执行文件,这意味着需要将 `--enable-preview` 标志传递给Surefire插件。将 `<argLine>--enable-preview</argLine>` 添加到其 `configuration` 片段是一种可行方法。
====

=== 作为原生可执行文件运行时排除测试

当以这种方式运行测试时,唯一真正在本地运行的是你的应用程序端点,你只能通过HTTP调用来测试。你的测试代码实际上并不在本地运行,所以如果你测试的代码不调用你的HTTP端点,把它们作为本地测试的一部分运行可能不是一个好主意。

If you share your test class between JVM and native executions like we advise above, you can mark certain tests with the `@DisabledOnIntegrationTest` annotation in order to skip them when testing against a native image.

[NOTE]
====
使用 `@DisabledOnIntegrationTest` 还将禁用所有集成测试实例中的测试,包括在JVM模式、容器镜像和原生镜像中测试应用程序。
====

=== 测试一个现有的原生可执行文件

It is also possible to re-run the tests against a native executable that has already been built. To do this run `./mvnw test-compile failsafe:integration-test -Pnative`. This will discover the existing native image and run the tests against it using failsafe.

如果进程由于某种原因找不到原生镜像,或者你想测试一个已经不在目标目录中的原生镜像,你可以用 `-Dnative.image.path=` 系统属性指定可执行文件。

[#container-runtime]
== 在没有安装GraalVM的情况下创建一个Linux可执行文件

IMPORTANT: 在进一步行动之前,请确保有一个工作的容器运行环境(Docker或podman)。如果你在Windows上使用Docker,你应该在Docker Desktop文件共享设置中共享你的项目的驱动器,并重新启动Docker Desktop。

很多时候,人们只需要为他们的Quarkus应用程序创建一个原生Linux可执行文件(例如,为了在容器化环境中运行),并希望避免安装适当的GraalVM版本来完成这项麻烦任务(例如,在CI环境中,通常的做法是尽可能少地安装软件)。

为此,Quarkus提供了一个非常方便的方法,通过利用容器运行时(如Docker或podman)来创建一个原生Linux可执行文件。完成这项任务的最简单方法是执行:

[source, bash, subs=attributes+,,  role="primary asciidoc-tabs-sync-cli"]
.CLI
----
quarkus build --native --no-tests -Dquarkus.native.container-build=true
# The --no-tests flag is required only on Windows and macOS.
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-maven"]
.Maven
----
./mvnw package -Dnative -Dquarkus.native.container-build=true
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-gradle"]
.Gradle
----
./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true
----

[TIP]
====
By default, Quarkus automatically detects the container runtime. If you want to explicitly select the container runtime, you can do it with:

对于Docker:

:build-additional-parameters: -Dquarkus.native.container-runtime=docker
[source, bash, subs=attributes+,,  role="primary asciidoc-tabs-sync-cli"]
.CLI
----
quarkus build --native -Dquarkus.native.container-build=true {build-additional-parameters}
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-maven"]
.Maven
----
./mvnw package -Dnative -Dquarkus.native.container-build=true {build-additional-parameters}
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-gradle"]
.Gradle
----
./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true {build-additional-parameters}
----
:!build-additional-parameters:

对于podman:

:build-additional-parameters: -Dquarkus.native.container-runtime=podman
[source, bash, subs=attributes+,,  role="primary asciidoc-tabs-sync-cli"]
.CLI
----
quarkus build --native -Dquarkus.native.container-build=true {build-additional-parameters}
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-maven"]
.Maven
----
./mvnw package -Dnative -Dquarkus.native.container-build=true {build-additional-parameters}
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-gradle"]
.Gradle
----
./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true {build-additional-parameters}
----
:!build-additional-parameters:

这些是标准的Quarkus配置属性,所以如果你总是想在容器中构建,建议你把这些添加到你的 `application.properties` ,以避免每次都指定它们。
====

[TIP]
====
如果你在试图使用容器构建创建原生可执行文件时,尽管你的JAR已经成功构建,仍看到应用程序JAR出现以下无效路径错误,您很可能为容器运行时使用了一个远程守护进程。
----
Error: Invalid Path entry getting-started-1.0.0-SNAPSHOT-runner.jar
Caused by: java.nio.file.NoSuchFileException: /project/getting-started-1.0.0-SNAPSHOT-runner.jar
----
在这种情况下,使用参数 `-Dquarkus.native.remote-container-build=true` ,而不是 `-Dquarkus.native.container-build=true` 。

原因是通过 `-Dquarkus.native.container-build=true` 调用的本地构建驱动程序使用卷挂载来使 JAR 在构建容器中可用,但卷挂载对远程守护程序不起作用。远程容器构建驱动程序复制必要的文件,而不是挂载它们。请注意,即使远程驱动程序也能与本地守护进程一起工作,但在本地情况下,本地驱动程序应该是首选,因为挂载通常比复制性能更高。
====

[TIP]
====
使用Mandrel构建需要额外传递一个自定义的构建器镜像参数:

:build-additional-parameters: -Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-mandrel:{mandrel-flavor}
[source, bash, subs=attributes+,,  role="primary asciidoc-tabs-sync-cli"]
.CLI
----
quarkus build --native -Dquarkus.native.container-build=true {build-additional-parameters}
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-maven"]
.Maven
----
./mvnw package -Dnative -Dquarkus.native.container-build=true {build-additional-parameters}
----
[source, bash, subs=attributes+,,  role="secondary asciidoc-tabs-sync-gradle"]
.Gradle
----
./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true {build-additional-parameters}
----
:!build-additional-parameters:

请注意,上述命令指向的是一个浮动标签。我们强烈建议你使用浮动标签,这样你的构建器镜像就能保持最新和安全。如果你一定要硬编码到一个特定的标签(参见 https://quay.io/repository/quarkus/ubi-quarkus-mandrel?tab=tags[这里] 的可用标签),但要注意,你不会得到安全更新,而且这不被支持。
====

== 创建一个容器

=== 使用容器-镜像扩展

到目前为止,从你的Quarkus应用程序中创建一个容器镜像的最简单方法是利用容器镜像扩展。

如果这些扩展之一是存在的,那么为原生可执行文件创建一个容器镜像基本上就是执行一个命令的问题:

[source, bash]
----
./mvnw package -Pnative -Dquarkus.native.container-build=true -Dquarkus.container-image.build=true
----

* `quarkus.native.container-build=true` 允许在不安装GralVM的情况下创建一个Linux可执行文件(只有在你没有安装GralVM或者你的本地操作系统不是Linux的情况下才需要)
* `quarkus.container-image.build=true` 指示Quarkus使用最终的应用程序工件(在本例中是原生可执行文件)创建一个容器镜像

更多细节见 xref:container-image.adoc[容器镜像指南] 。

=== 手动使用微基础镜像

你可以使用Quarkus Maven插件生成的JAR在容器中运行该应用程序。然而,在本节中我们将重点讨论使用生成的原生可执行文件创建一个容器镜像。

image:containerization-process.png[容器化过程]

使用本地GraalVM安装时,原生可执行文件的目标是您的本地操作系统(Linux、macOS、Windows等)。然而,由于容器可能不使用与操作系统相同的 _executable_ 格式,我们将指示Maven构建通过利用容器运行时( 如 <<#container-runtime,this section>> 所述)来生成可执行文件:

The produced executable will be a 64-bit Linux executable, so depending on your operating system it may no longer be runnable. However, it's not an issue as we are going to copy it to a container. The project generation has provided a `Dockerfile.native-micro` in the `src/main/docker` directory with the following content:

[source, dockerfile]
----
FROM quay.io/quarkus/quarkus-micro-image:1.0
WORKDIR /work/
COPY target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
----

[NOTE]
.什么是Quarkus微镜像?
====
Quarkus 微镜像是一个小型的容器镜像,为运行你的原生应用程序提供了正确的依赖性集合。它是基于 https://catalog.redhat.com/software/containers/ubi8-micro/601a84aadd19c7786c47c8ea?container-tabs=overview[UBI Micro] 的。这个基础镜像已经被定制为在容器中完美运行。

你可以在这里阅读更多关于UBI镜像的内容:

* https://www.redhat.com/en/blog/introducing-red-hat-universal-base-image[通用基础镜像介绍]
* https://catalog.redhat.com/software/container-stacks/detail/5ec53f50ef29fd35586d9a56[红帽通用基础镜像8]

UBI镜像可以不受任何限制地使用。

xref:quarkus-runtime-base-image.adoc[此页] 解释了当你的应用有特殊要求时,如何扩展 `quarkus-micro` 镜像。
====

然后,如果你没有删除生成的原生可执行文件,可以用以下方法构建docker镜像:

[source, bash]
----
docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/getting-started .
----

最后,用以下方式运行:

[source, bash]
----
docker run -i --rm -p 8080:8080 quarkus-quickstart/getting-started
----

=== 手工使用最小基础镜像

生成的项目也在 `src/main/docker` 目录中提供了一个 `Dockerfile.native` ,内容如下:

[source, dockerfile]
----
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5
WORKDIR /work/
COPY target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
----

UBI最小镜像比上面提到的微镜像要大。它包含更多的实用程序,如 `microdnf` 软件包管理器。

[#multistage-docker]
=== 使用多阶段的Docker构建

上一节向你展示了如何使用Maven或Gradle构建原生可执行文件,但这需要你先创建原生可执行文件。此外,这个原生可执行文件必须是Linux 64位可执行文件。

你可能想直接在一个容器中构建原生可执行文件,而不需要一个包含构建工具的最终容器。这种方法可以通过多阶段的Docker构建来实现:

1. 第一阶段使用Maven或Gradle构建原生可执行文件
2. 第二阶段是复制产生了原生可执行文件的最小镜像

这样的多阶段构建可以通过以下方式实现:

用Maven构建的Docker文件例子:
[source, dockerfile, subs=attributes+]
----
## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-flavor} AS build
COPY --chown=quarkus:quarkus mvnw /code/mvnw
COPY --chown=quarkus:quarkus .mvn /code/.mvn
COPY --chown=quarkus:quarkus pom.xml /code/
USER quarkus
WORKDIR /code
RUN ./mvnw -B org.apache.maven.plugins:maven-dependency-plugin:3.1.2:go-offline
COPY src /code/src
RUN ./mvnw package -Pnative

## Stage 2 : create the docker final image
FROM quay.io/quarkus/quarkus-micro-image:1.0
WORKDIR /work/
COPY --from=build /code/target/*-runner /work/application

# set up permissions for user `1001`
RUN chmod 775 /work /work/application \
  && chown -R 1001 /work \
  && chmod -R "g+rwX" /work \
  && chown -R 1001:root /work

EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
----

NOTE: 这种多阶段Docker构建从主机上复制Maven包装器。Maven包装器(或Gradle包装器)是提供特定版本Maven/Gradle的一种便捷方式。它避免了用Maven和Gradle创建一个基础镜像。要在项目中配置Maven包装器,请使用: `mvn -N org.apache.maven.plugins:maven-wrapper-plugin:3.1.0:wrapper` 。

将此文件保存在 `src/main/docker/Dockerfile.multistage` ,因为它不包括在开始快速入门中。

用Gradle构建的Docker文件例子:
[source, dockerfile, subs=attributes+]
----
## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-flavor} AS build
USER root
RUN microdnf install findutils
COPY --chown=quarkus:quarkus gradlew /code/gradlew
COPY --chown=quarkus:quarkus gradle /code/gradle
COPY --chown=quarkus:quarkus build.gradle /code/
COPY --chown=quarkus:quarkus settings.gradle /code/
COPY --chown=quarkus:quarkus gradle.properties /code/
USER quarkus
WORKDIR /code
COPY src /code/src
RUN ./gradlew build -Dquarkus.package.type=native

## Stage 2 : create the docker final image
FROM quay.io/quarkus/quarkus-micro-image:1.0
WORKDIR /work/
COPY --from=build /code/build/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
----

如果在项目中使用Gradle,你可以使用这个Docker文件例子。将其保存在 `src/main/docker/Dockerfile.multistage` 。

[WARNING]
====
在启动我们的Docker构建之前,我们需要更新默认的 `.dockerignore` 文件,因为它过滤了除 `target` 目录之外的所有内容。由于我们计划在容器内构建,我们需要复制 `src` 目录。因此,编辑你的 `.dockerignore` ,并更新内容。
====

[source, bash]
----
docker build -f src/main/docker/Dockerfile.multistage -t quarkus-quickstart/getting-started .
----

最后,用以下方式运行:

[source, bash]
----
docker run -i --rm -p 8080:8080 quarkus-quickstart/getting-started
----

[TIP]
====
如果你的原生可执行文件需要SSL支持,你可以轻松地在Docker镜像中包含必要的库。

更多信息请参见 xref:native-and-ssl.adoc#working-with-containers[我们的使用SSL与原生可执行文件指南] 。
====

NOTE: 要使用Mandrel而不是GraalVM CE,请将 `FROM` 子句更新为: `FROM quay.io/quarkus/ubi-quarkus-mandrel:$TAG AS build` 。 `$TAG` 可以在 https://quay.io/repository/quarkus/ubi-quarkus-mandrel?tab=tags[Quarkus Mandrel镜像标签页]上找到。

=== 使用无发行版基础镜像

IMPORTANT: 无发行版支持是试验性的。

如果你正在寻找小型的容器镜像,https://github.com/GoogleContainerTools/distroless[无发行] 的方法可以减少基础层的大小。 _distroless_ 背后的想法是使用一个单一和最小的基础镜像包含所有的需求,有时甚至是应用程序本身。

Quarkus提供了一个无发行版的基础镜像,可以用于你的 `Dockerfile` 。你只需要复制你的应用程序,就可以了:

[source, dockerfile]
----
FROM quay.io/quarkus/quarkus-distroless-image:1.0
COPY target/*-runner /application

EXPOSE 8080
USER nonroot

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
----

Quarkus提供了 `quay.io/quarkus/quarkus-distroless-image:1.0` 镜像。它包含了运行原生可执行文件所需的软件包,并且只有 *9Mb* 。只要在这个镜像上添加你的应用程序,你就会得到一个很小的容器镜像。

在没有经过严格测试的情况下,不应该在生产中使用无发行版镜像。

=== Using a scratch base image

IMPORTANT: Scratch image support is experimental.

Building fully statically linked binaries enables the usage of a https://hub.docker.com/_/scratch[scratch image] containing solely the resulting native executable.

Sample multistage Dockerfile for building an image from `scratch`:

[source, dockerfile]
----
## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi-quarkus-native-image:22.0-java11 AS build
USER root
RUN microdnf install make gcc
COPY --chown=quarkus:quarkus mvnw /code/mvnw
COPY --chown=quarkus:quarkus .mvn /code/.mvn
COPY --chown=quarkus:quarkus pom.xml /code/
RUN mkdir /musl && \
    curl -L -o musl.tar.gz https://more.musl.cc/10.2.1/x86_64-linux-musl/x86_64-linux-musl-native.tgz && \
    tar -xvzf musl.tar.gz -C /musl --strip-components 1 && \
    curl -L -o zlib.tar.gz https://zlib.net/zlib-1.2.12.tar.gz && \
    mkdir zlib && tar -xvzf zlib.tar.gz -C zlib --strip-components 1 && \
    cd zlib && ./configure --static --prefix=/musl && \
    make && make install && \
    cd .. && rm -rf zlib && rm -f zlib.tar.gz && rm -f musl.tar.gz
ENV PATH="/musl/bin:${PATH}"
USER quarkus
WORKDIR /code
RUN ./mvnw -B org.apache.maven.plugins:maven-dependency-plugin:3.1.2:go-offline
COPY src /code/src
RUN ./mvnw package -Pnative -Dquarkus.native.additional-build-args="--static","--libc=musl"

## Stage 2 : create the docker final image
FROM scratch
COPY --from=build /code/target/*-runner /application
ENTRYPOINT [ "/application" ]
----

Scratch images should not be used in production without rigorous testing.

=== 原生可执行文件压缩

Quarkus可以使用UPX压缩产生的原生可执行文件。更多细节见 xref:./upx.adoc[UPX压缩文档] 。

=== Java和原生镜像分开编译

In certain circumstances, you may want to build the native image in a separate step. For example, in a CI/CD pipeline, you may want to have one step to generate the source that will be used for the native image generation and another step to use these sources to actually build the native executable. For this use case, you can set the `quarkus.package.type=native-sources`. This will execute the java compilation as if you had started native compilation (`-Pnative`), but stops before triggering the actual call to GraalVM's `native-image`.

[source, bash]
----
$ ./mvnw clean package -Dquarkus.package.type=native-sources
----

编译完成后,你可以在 `target/native-sources` 找到构建工件:

[source, bash]
----
$ cd target/native-sources
$ ls
native-image.args  getting-started-1.0.0-SNAPSHOT-runner.jar lib
----

从上面的输出可以看出,除了生成的jar文件和相关的lib目录外,还创建了一个名为 `native-image.args` 的文本文件。这个文件包含了所有的参数(包括要编译的JAR的名字),以及传递给GraalVM的 `native-image` 命令。如果你已经安装了GraalVM,你可以通过执行以下命令开始本地编译:

[source, bash]
----
$ cd target/native-source
$ native-image $(cat native-image.args)
...
$ ls
native-image.args
getting-started-1.0.0-SNAPSHOT-runner
getting-started-1.0.0-SNAPSHOT-runner.build_artifacts.txt
getting-started-1.0.0-SNAPSHOT-runner.jar
----

Gradle的过程是类似的。

在一个容器中运行构建过程也是可能的:

[source, bash, subs=attributes+]
----
cd target/native-image
docker run \
  -it \
  --rm \
  --v $(pwd):/work (1)
  -w /work (2)
  --entrypoint bin/sh \
  quay.io/quarkus/ubi-quarkus-native-image:{graalvm-flavor} \ (3)
  -c "native-image $(cat native-image.args) -J-Xmx4g" (4)
----

<1> 将主机的目录 `target/native-image` 挂载到容器的 `/work` 。因此,生成的二进制文件也将被写入这个目录。
<2> 将工作目录切换到 `/work` ,我们已经在<1>中挂载了这个目录。
<3> 使用 <<#multistage-docker,Using a multi-stage Docker build>> 中介绍的 `quay.io/quarkus/ubi-quarkus-native-image:{graalvm-flavor}` docker镜像来构建原生镜像。
<4> 以文件 `native-image.args` 的内容为参数调用 `native-image` 。我们还提供了一个额外的参数,将进程的最大内存限制在4G字节(这可能取决于正在构建的项目和构建它的机器)。

[WARNING]
====
如果你是在Windows机器上运行,请记住,二进制文件是在Linux docker容器中创建的。因此,二进制文件在Windows主机上是无法执行的。
====

以下是对CI/CD管道的各个步骤的高度概述:

1. 将执行 `./mvnw …​` 命令的步骤的输出(即目录 `target/native-image` )注册为构建工件,
2. 在执行 `native-image …​` 命令的步骤中需要这个工件,并且
3. 将执行 `native-image …​` 命令的步骤的输出(即匹配 `target/*runner` 的文件)注册为构建工件。

执行步骤 `1` 的环境只需要安装Java和Maven(或Gradle),而执行步骤 `3` 的环境只需要安装GralVM(包括 `native-image` 功能)。

根据CI/CD管道的最终期望输出,生成的二进制文件可能被用来创建一个容器镜像。

== 调试原生可执行文件

从Oracle GraalVM 20.2或Mandrel 20.1开始,可以为Linux环境生成原生可执行文件的调试符号(Windows支持仍在开发中,不支持macOS)。这些符号可用于用工具调试原生可执行文件,如 `gdb` 。

要生成调试符号,在生成原生可执行文件时添加 `-Dquarkus.native.debug.enabled=true` 标志。你将在原生可执行文件旁边的 `.debug` 文件中找到原生可执行文件的调试符号。

[NOTE]
====
`.debug` 文件的生成取决于 `objcopy` 。在常见的Linux发行版上,你将需要安装 `binutils` 包:

[source, bash]
----
# dnf (rpm-based)
sudo dnf install binutils
# Debian-based distributions
sudo apt-get install binutils
----

当被嵌入到可执行文件中的 `objcopy` 调试符号不可用时。
====

除了调试符号外,设置 `-Dquarkus.native.debug.enabled=true` 标志会生成一个源文件缓存,用于生成原生可执行文件时解决的任何JDK运行时类、GraalVM类和应用程序类。这个源码缓存对原生调试工具很有用,可以在符号和匹配的源代码之间建立联系。在调试本原生执行文件时,它提供了一种方便的方法,使调试器/IDE仅能获得必要的源文件。

第三方jar依赖的源,包括Quarkus源代码,默认情况下不会被添加到源缓存中。要包括这些,请确保你先调用 `mvn dependency:sources` 。这一步是必须的,以便拉出这些依赖的源代码,并将其包含在源代码缓存中。

源缓存位于 `target/sources` 文件夹中。

[TIP]
====
如果从与 `target` 不同的目录下运行 `gdb` ,那么可以通过运行源代码加载:

[source, bash]
----
directory path/to/target
----

在 `gdb` 提示中。

或这样运行 `gdb` 命令:

[source, bash]
----
gdb -ex 'directory path/to/target' path/to/target/{project.name}-{project.version}-runner
----

比如:
[source, bash]
----
gdb -ex 'directory ./target' ./target/getting-started-1.0.0-SNAPSHOT-runner
----
====

关于调试原生镜像的更详细指南,请参考 xref:native-reference.adoc[原生参考指南] 。

[[configuration-reference]]
== 配置原生可执行文件

有很多不同的配置选项可以影响原生可执行文件的生成方式。这些都是在 `application.properties` ,与其他配置属性相同。

这些属性显示如下:


:summaryTableId: quarkus-native-pkg-native-config
[.configuration-legend]
icon:lock[title=Fixed at build time] Configuration property fixed at build time - All other configuration properties are overridable at runtime
[.configuration-reference, cols="80,.^10,.^10"]
|===

h|[[quarkus-native-pkg-native-config_configuration]]link:#quarkus-native-pkg-native-config_configuration[Configuration property]

h|类型
h|默认

a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.additional-build-args]]`link:#quarkus-native-pkg-native-config_quarkus.native.additional-build-args[quarkus.native.additional-build-args]`

[.description]
--
Comma-separated, additional arguments to pass to the build process. If an argument includes the `,` symbol, it needs to be escaped, e.g. `++\\++,`

Environment variable: `+++QUARKUS_NATIVE_ADDITIONAL_BUILD_ARGS+++`
--|list of string
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.enable-http-url-handler]]`link:#quarkus-native-pkg-native-config_quarkus.native.enable-http-url-handler[quarkus.native.enable-http-url-handler]`

[.description]
--
If the HTTP url handler should be enabled, allowing you to do URL.openConnection() for HTTP URLs

Environment variable: `+++QUARKUS_NATIVE_ENABLE_HTTP_URL_HANDLER+++`
--|boolean
|`true`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.enable-https-url-handler]]`link:#quarkus-native-pkg-native-config_quarkus.native.enable-https-url-handler[quarkus.native.enable-https-url-handler]`

[.description]
--
If the HTTPS url handler should be enabled, allowing you to do URL.openConnection() for HTTPS URLs

Environment variable: `+++QUARKUS_NATIVE_ENABLE_HTTPS_URL_HANDLER+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.inline-before-analysis]]`link:#quarkus-native-pkg-native-config_quarkus.native.inline-before-analysis[quarkus.native.inline-before-analysis]`

[.description]
--
If `-H:{plus}InlineBeforeAnalysis` flag will be added to the native-image run

Environment variable: `+++QUARKUS_NATIVE_INLINE_BEFORE_ANALYSIS+++`
--|boolean
|`true`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.headless]]`link:#quarkus-native-pkg-native-config_quarkus.native.headless[quarkus.native.headless]`

[.description]
--
The default value for java.awt.headless JVM option. Switching this option affects linking of awt libraries.

Environment variable: `+++QUARKUS_NATIVE_HEADLESS+++`
--|boolean
|`true`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.file-encoding]]`link:#quarkus-native-pkg-native-config_quarkus.native.file-encoding[quarkus.native.file-encoding]`

[.description]
--
Defines the file encoding as in `-Dfile.encoding=...`. Native image runtime uses the host's (i.e. build time) value of `file.encoding` system property. We intentionally default this to UTF-8 to avoid platform specific defaults to be picked up which can then result in inconsistent behavior in the generated native executable.

Environment variable: `+++QUARKUS_NATIVE_FILE_ENCODING+++`
--|string
|`UTF-8`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.add-all-charsets]]`link:#quarkus-native-pkg-native-config_quarkus.native.add-all-charsets[quarkus.native.add-all-charsets]`

[.description]
--
If all character sets should be added to the native image. This increases image size

Environment variable: `+++QUARKUS_NATIVE_ADD_ALL_CHARSETS+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.graalvm-home]]`link:#quarkus-native-pkg-native-config_quarkus.native.graalvm-home[quarkus.native.graalvm-home]`

[.description]
--
The location of the Graal distribution

Environment variable: `+++QUARKUS_NATIVE_GRAALVM_HOME+++`
--|string
|`${GRAALVM_HOME:}`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.java-home]]`link:#quarkus-native-pkg-native-config_quarkus.native.java-home[quarkus.native.java-home]`

[.description]
--
The location of the JDK

Environment variable: `+++QUARKUS_NATIVE_JAVA_HOME+++`
--|link:https://docs.oracle.com/javase/8/docs/api/java/io/File.html[File]

|`${java.home}`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.native-image-xmx]]`link:#quarkus-native-pkg-native-config_quarkus.native.native-image-xmx[quarkus.native.native-image-xmx]`

[.description]
--
The maximum Java heap to be used during the native image generation

Environment variable: `+++QUARKUS_NATIVE_NATIVE_IMAGE_XMX+++`
--|string
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.debug-build-process]]`link:#quarkus-native-pkg-native-config_quarkus.native.debug-build-process[quarkus.native.debug-build-process]`

[.description]
--
If the native image build should wait for a debugger to be attached before running. This is an advanced option and is generally only intended for those familiar with GraalVM internals

Environment variable: `+++QUARKUS_NATIVE_DEBUG_BUILD_PROCESS+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.publish-debug-build-process-port]]`link:#quarkus-native-pkg-native-config_quarkus.native.publish-debug-build-process-port[quarkus.native.publish-debug-build-process-port]`

[.description]
--
If the debug port should be published when building with docker and debug-build-process is true

Environment variable: `+++QUARKUS_NATIVE_PUBLISH_DEBUG_BUILD_PROCESS_PORT+++`
--|boolean
|`true`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.enable-isolates]]`link:#quarkus-native-pkg-native-config_quarkus.native.enable-isolates[quarkus.native.enable-isolates]`

[.description]
--
If isolates should be enabled

Environment variable: `+++QUARKUS_NATIVE_ENABLE_ISOLATES+++`
--|boolean
|`true`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.enable-fallback-images]]`link:#quarkus-native-pkg-native-config_quarkus.native.enable-fallback-images[quarkus.native.enable-fallback-images]`

[.description]
--
If a JVM based 'fallback image' should be created if native image fails. This is not recommended, as this is functionally the same as just running the application in a JVM

Environment variable: `+++QUARKUS_NATIVE_ENABLE_FALLBACK_IMAGES+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.auto-service-loader-registration]]`link:#quarkus-native-pkg-native-config_quarkus.native.auto-service-loader-registration[quarkus.native.auto-service-loader-registration]`

[.description]
--
If all META-INF/services entries should be automatically registered

Environment variable: `+++QUARKUS_NATIVE_AUTO_SERVICE_LOADER_REGISTRATION+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.dump-proxies]]`link:#quarkus-native-pkg-native-config_quarkus.native.dump-proxies[quarkus.native.dump-proxies]`

[.description]
--
If the bytecode of all proxies should be dumped for inspection

Environment variable: `+++QUARKUS_NATIVE_DUMP_PROXIES+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.container-build]]`link:#quarkus-native-pkg-native-config_quarkus.native.container-build[quarkus.native.container-build]`

[.description]
--
If this build should be done using a container runtime. Unless container-runtime is also set, docker will be used by default. If docker is not available or is an alias to podman, podman will be used instead as the default.

Environment variable: `+++QUARKUS_NATIVE_CONTAINER_BUILD+++`
--|boolean
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.remote-container-build]]`link:#quarkus-native-pkg-native-config_quarkus.native.remote-container-build[quarkus.native.remote-container-build]`

[.description]
--
If this build is done using a remote docker daemon.

Environment variable: `+++QUARKUS_NATIVE_REMOTE_CONTAINER_BUILD+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.builder-image]]`link:#quarkus-native-pkg-native-config_quarkus.native.builder-image[quarkus.native.builder-image]`

[.description]
--
The docker image to use to do the image build. It can be one of `graalvm`, `mandrel`, or the full image path, e.g. `quay.io/quarkus/ubi-quarkus-mandrel:21.3-java17`.

Environment variable: `+++QUARKUS_NATIVE_BUILDER_IMAGE+++`
--|string
|`${platform.quarkus.native.builder-image}`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.container-runtime]]`link:#quarkus-native-pkg-native-config_quarkus.native.container-runtime[quarkus.native.container-runtime]`

[.description]
--
The container runtime (e.g. docker) that is used to do an image based build. If this is set then a container build is always done.

Environment variable: `+++QUARKUS_NATIVE_CONTAINER_RUNTIME+++`
-- a|
`docker`, `podman`
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.container-runtime-options]]`link:#quarkus-native-pkg-native-config_quarkus.native.container-runtime-options[quarkus.native.container-runtime-options]`

[.description]
--
Options to pass to the container runtime

Environment variable: `+++QUARKUS_NATIVE_CONTAINER_RUNTIME_OPTIONS+++`
--|list of string
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.enable-vm-inspection]]`link:#quarkus-native-pkg-native-config_quarkus.native.enable-vm-inspection[quarkus.native.enable-vm-inspection]`

[.description]
--
If the resulting image should allow VM introspection

Environment variable: `+++QUARKUS_NATIVE_ENABLE_VM_INSPECTION+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.full-stack-traces]]`link:#quarkus-native-pkg-native-config_quarkus.native.full-stack-traces[quarkus.native.full-stack-traces]`

[.description]
--
If full stack traces are enabled in the resulting image

Environment variable: `+++QUARKUS_NATIVE_FULL_STACK_TRACES+++`
--|boolean
|`true`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.enable-reports]]`link:#quarkus-native-pkg-native-config_quarkus.native.enable-reports[quarkus.native.enable-reports]`

[.description]
--
If the reports on call paths and included packages/classes/methods should be generated

Environment variable: `+++QUARKUS_NATIVE_ENABLE_REPORTS+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.report-exception-stack-traces]]`link:#quarkus-native-pkg-native-config_quarkus.native.report-exception-stack-traces[quarkus.native.report-exception-stack-traces]`

[.description]
--
If exceptions should be reported with a full stack trace

Environment variable: `+++QUARKUS_NATIVE_REPORT_EXCEPTION_STACK_TRACES+++`
--|boolean
|`true`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.report-errors-at-runtime]]`link:#quarkus-native-pkg-native-config_quarkus.native.report-errors-at-runtime[quarkus.native.report-errors-at-runtime]`

[.description]
--
If errors should be reported at runtime. This is a more relaxed setting, however it is not recommended as it means your application may fail at runtime if an unsupported feature is used by accident.

Environment variable: `+++QUARKUS_NATIVE_REPORT_ERRORS_AT_RUNTIME+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.reuse-existing]]`link:#quarkus-native-pkg-native-config_quarkus.native.reuse-existing[quarkus.native.reuse-existing]`

[.description]
--
Don't build a native image if it already exists. This is useful if you have already built an image and you want to use Quarkus to deploy it somewhere. Note that this is not able to detect if the existing image is outdated, if you have modified source or config and want a new image you must not use this flag.

Environment variable: `+++QUARKUS_NATIVE_REUSE_EXISTING+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.resources.includes]]`link:#quarkus-native-pkg-native-config_quarkus.native.resources.includes[quarkus.native.resources.includes]`

[.description]
--
A comma separated list of globs to match resource paths that should be added to the native image.
 Use slash (`/`) as a path separator on all platforms. Globs must not start with slash.
 By default, no resources are included.
 Example: Given that you have `src/main/resources/ignored.png` and `src/main/resources/foo/selected.png` in your source tree and one of your dependency JARs contains `bar/some.txt` file, with the following configuration quarkus.native.resources.includes = foo/++**++,bar/++**++/++*++.txt  the files `src/main/resources/foo/selected.png` and `bar/some.txt` will be included in the native image, while `src/main/resources/ignored.png` will not be included.
 Supported glob features   Feature Description   `++*++` Matches a (possibly empty) sequence of characters that does not contain slash (`/`)   `++**++` Matches a (possibly empty) sequence of characters that may contain slash (`/`)   `?` Matches one character, but not slash   `++[++abc++]++` Matches one character given in the bracket, but not slash   `++[++a-z++]++` Matches one character from the range given in the bracket, but not slash   `++[++!abc++]++` Matches one character not named in the bracket; does not match slash   `++[++a-z++]++` Matches one character outside the range given in the bracket; does not match slash   `++{++one,two,three++}++` Matches any of the alternating tokens separated by comma; the tokens may contain wildcards, nested alternations and ranges   `++\++` The escape character
 Note that there are three levels of escaping when passing this option via `application.properties`:
 . `application.properties` parser
 - MicroProfile Config list converter that splits the comma separated list
 - Glob parser  All three levels use backslash (`++\++`) as the escaping character. So you need to use an appropriate number of backslashes depending on which level you want to escape.
 Note that Quarkus extensions typically include the resources they require by themselves. This option is useful in situations when the built-in functionality is not sufficient.

Environment variable: `+++QUARKUS_NATIVE_RESOURCES_INCLUDES+++`
--|list of string
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.resources.excludes]]`link:#quarkus-native-pkg-native-config_quarkus.native.resources.excludes[quarkus.native.resources.excludes]`

[.description]
--
A comma separated list of globs to match resource paths that should *not* be added to the native image.
 Use slash (`/`) as a path separator on all platforms. Globs must not start with slash.
 Please refer to `includes` for details about the glob syntax.
 By default, no resources are excluded.
 Example: Given that you have `src/main/resources/red.png` and `src/main/resources/foo/green.png` in your source tree and one of your dependency JARs contains `bar/blue.png` file, with the following configuration quarkus.native.resources.includes = ++**++/++*++.png quarkus.native.resources.excludes = foo/++**++,++**++/green.png  the resource `red.png` will be available in the native image while the resources `foo/green.png` and `bar/blue.png` will not be available in the native image.

Environment variable: `+++QUARKUS_NATIVE_RESOURCES_EXCLUDES+++`
--|list of string
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.debug.enabled]]`link:#quarkus-native-pkg-native-config_quarkus.native.debug.enabled[quarkus.native.debug.enabled]`

[.description]
--
If debug is enabled and debug symbols are generated. The symbols will be generated in a separate .debug file.

Environment variable: `+++QUARKUS_NATIVE_DEBUG_ENABLED+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.enable-dashboard-dump]]`link:#quarkus-native-pkg-native-config_quarkus.native.enable-dashboard-dump[quarkus.native.enable-dashboard-dump]`

[.description]
--
Generate the report files for GraalVM Dashboard.

Environment variable: `+++QUARKUS_NATIVE_ENABLE_DASHBOARD_DUMP+++`
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.compression.level]]`link:#quarkus-native-pkg-native-config_quarkus.native.compression.level[quarkus.native.compression.level]`

[.description]
--
The compression level in ++[++1, 10++]++. 10 means *best* Higher compression level requires more time to compress the executable.

Environment variable: `+++QUARKUS_NATIVE_COMPRESSION_LEVEL+++`
--|int
|


a|icon:lock[title=Fixed at build time] [[quarkus-native-pkg-native-config_quarkus.native.compression.additional-args]]`link:#quarkus-native-pkg-native-config_quarkus.native.compression.additional-args[quarkus.native.compression.additional-args]`

[.description]
--
Allows passing extra arguments to the UPX command line (like --brute). The arguments are comma-separated. The exhaustive list of parameters can be found in link:https://github.com/upx/upx/blob/devel/doc/upx.pod[https://github.com/upx/upx/blob/devel/doc/upx.pod].

Environment variable: `+++QUARKUS_NATIVE_COMPRESSION_ADDITIONAL_ARGS+++`
--|list of string
|

|===

== 下一步做什么?

本指南介绍了如何为应用程序创建原生(二进制)可执行文件。它提供了一个具备快速启动时间和消耗更少内存的应用程序。然而,还有更多。

我们建议继续阅读 xref:deploying-to-kubernetes.adoc[部署到Kubernetes和OpenShift]。