Deploying to Heroku
本指南将介绍如何基于 Quarkus 的 Web 应用程序部署为 Heroku 的 Web-dyno。 本指南涵盖:
-
Update Quarkus HTTP Port
-
Install the Heroku CLI
-
将应用程序部署到 Heroku
-
将应用程序作为容器镜像部署到 Heroku
-
Using Docker
-
Using Podman
-
将本机应用程序作为容器镜像部署到 Heroku
Prerequisites
如要完成本指南,您需要:
-
Roughly 15 minutes
-
An IDE
-
安装了 JDK 17+,已正确配置
JAVA_HOME
-
Apache Maven ${proposed-maven-version}
-
如果你想使用 Quarkus CLI, 则可以选择使用
-
如果你想构建一个本机可执行文件(或如果你使用本机容器构建,则使用 Docker),则可以选择安装 Mandrel 或 GraalVM 以及 configured appropriately
Introduction
Heroku 是平台即服务 (PaaS),它使开发人员能够完全在云中构建、运行和操作应用程序。它支持多种语言,如 Java、Ruby、Node.js、Scala、Clojure、Python、PHP 和 Go。此外,它还提供一个容器注册表,可用于部署预构建的容器镜像。
Heroku 可通过以下不同的方式用于运行 Quarkus 应用程序:
-
作为普通 Java 程序,在 Heroku 的环境定义的容器中运行
-
作为容器化的 Java 程序,在由 Quarkus 构建过程定义的容器中运行
-
作为容器化的本机程序,在由 Quarkus 构建过程定义的容器中运行
所有这三种方法都需要知道 Heroku 分配给它的端口,以处理流量。幸运的是,为此提供了一个动态配置属性。
Common project setup
本指南将以在 Getting Started guide中开发的应用程序作为输入。
确保您已准备好入门应用程序,或克隆 Git 存储库:git clone $${quickstarts-base-url}.git
,或下载一个 $${quickstarts-base-url}/archive/main.zip[存档]。解决方案位于 `getting-started`目录中。
Heroku 可以响应存储库中的更改,运行 CI 并在代码更改时重新部署应用程序。因此,我们从现有的有效存储库开始。
此外,请确保你的 Heroku CLI 正常工作:
heroku --version
heroku login
Prepare the Quarkus HTTP Port
Heroku 会选择一个随机端口,并将其分配给最终运行你 Quarkus 应用程序的容器。该端口作为环境变量在 `$PORT`下可用。在所有部署场景中使 Quarkus 意识到它的最简单方法是使用以下配置:
quarkus.http.port=${PORT:8080}
这可以理解为:“如果这是一个已定义的变量,则在 $PORT`上侦听,否则在 8080 上侦听(与通常的情况一样)。”运行以下命令将其添加到你的 `application.properties
:
echo "quarkus.http.port=\${PORT:8080}" >> src/main/resources/application.properties
git commit -am "Configure the HTTP Port."
Deploy the repository and build on Heroku
第一个变体使用 Quarkus Maven 构建来创建 _quarkus-app_应用程序结构,其中包含可运行的“fast-jar”以及在 Heroku 的构建基础设施内需要的所有库,然后部署该结果,另一个变体使用本地构建过程来创建优化容器。
对于第一个变体,你的应用程序根目录中需要两个其他文件:
-
system.properties
,用于配置 Java 版本 -
Procfile
,用于配置 Heroku 启动你的应用程序的方式
Quarkus 需要 JDK 17,所以我们首先指定它:
echo "java.runtime.version=17" >> system.properties
git add system.properties
git commit -am "Configure the Java version for Heroku."
我们将部署一个 Web 应用程序,因此我们需要在 Heroku Procfile
中配置类型 web
的应用程序,如下所示:
echo "web: java \$JAVA_OPTS -jar target/quarkus-app/quarkus-run.jar" >> Procfile
git add Procfile
git commit -am "Add a Procfile."
您的应用程序应该已经可以通过 heroku local web
运行。
让我们在您的账户中创建一个应用程序并向其部署该存储库:
heroku create
git push heroku master
heroku open
该应用程序将有一个生成的名称,终端应该输出该名称。 heroku open
打开您的默认浏览器以访问您的新应用程序。
要通过 curl 访问 REST 端点,请运行:
APP_NAME=`heroku info | grep "=== .*" |sed "s/=== //"`
curl $APP_NAME.herokuapp.com/hello
当然,您还可以使用 Heroku CLI 将此存储库连接到您的 GitHub 账户,但这不是本指南的讨论范围。
Deploy as container
推送完整容器的优势在于,我们可以完全控制其内容,甚至可以选择部署一个在 GraalVM 上运行本机可执行文件的容器。
首先,登录到 Heroku 的容器注册表:
heroku container:login
我们需要向我们的项目添加一个扩展,以通过 Quarkus Maven 插件构建容器映像:
mvn quarkus:add-extension -Dextensions="container-image-docker"
git add pom.xml
git commit -am "Add container-image-docker extension."
我们要构建的映像需要以符合 Heroku 的注册表和部署的方式进行命名。我们可以通过 heroku info
获得生成的名称,并将其传递到(本地)构建:
APP_NAME=`heroku info | grep "=== .*" |sed "s/=== //"`
mvn clean package\
-Dquarkus.container-image.build=true\
-Dquarkus.container-image.group=registry.heroku.com/$APP_NAME\
-Dquarkus.container-image.name=web\
-Dquarkus.container-image.tag=latest
Push and release the image
你现在可以推送映像并发布它。
初始推送相当大,因为映像的所有层都需要传输。后续推送会较小。 |
Pushing through Docker
安装 Docker 后,这些步骤很简单:
docker push registry.heroku.com/$APP_NAME/web
heroku container:release web --app $APP_NAME
Pushing through Podman
如果您想将 Podman 用作 Docker 的替代品,您将遇到一些问题,因为 Heroku CLI 依赖于 Docker,并且不支持 OCI 格式。但是,这些问题有可能的解决方案。
很明显,问题在于 heroku-cli 找不到 docker。这很容易解决,因为 podman cli 与 docker 兼容。我们只需要从 podman 创建一个到 docker 的符号链接:
sudo ln -s $(which podman) /usr/local/bin/docker
我们必须使用一种解决方法,以便通过 Podman 和 Heroku CLI 以所需的格式(v2s2 - Docker 映像清单版本 2,架构 2)推送和发布我们的应用程序,而不是执行常规的 podman 推送(OCI 格式)。还需要 skopeo。
CONTAINER_DIR="target/container-dir"
mkdir $CONTAINER_DIR
podman push --format=v2s2 "registry.heroku.com/$APP_NAME/web" dir:$CONTAINER_DIR
skopeo --debug copy dir:$CONTAINER_DIR "docker://registry.heroku.com/$APP_NAME/web:latest"
heroku container:release web --app "$APP_NAME"
rm -rf $CONTAINER_DIR
Deploy as native application inside a container
在将我们的应用程序部署为容器时,我们获得的最大优势是部署包含本机编译应用程序的容器。为什么?因为当没有传入流量时,Heroku 将停止或让应用程序进入休眠状态。本机应用程序将从休眠状态更快地唤醒。
该过程几乎完全相同。我们选择在一个本地容器内编译一个本机映像,以便我们不必在本地安装 GraalVM:
APP_NAME=`heroku info | grep "=== .*" |sed "s/=== //"`
mvn clean package\
-Dquarkus.container-image.build=true\
-Dquarkus.container-image.group=registry.heroku.com/$APP_NAME\
-Dquarkus.container-image.name=web\
-Dquarkus.container-image.tag=latest\
-Dnative\
-Dquarkus.native.container-build=true
然后再次使用 Docker 或 Podman 推入并发布(见上文),然后检查日志。