在 Azure 容器应用中使用 Quarkus 部署 Java 应用程序
本文介绍如何使用简单的 CRUD 应用程序在 Microsoft Azure 容器应用中快速部署 Red Hat Quarkus。 该应用程序是具有 JavaScript 前端和 REST 终结点的“待办事项列表”。 Azure Database for PostgreSQL 为应用提供持久性层。 本文介绍如何在本地测试应用并将其部署到容器应用。
先决条件
- 如果还没有 Azure 订阅,可以在开始前创建一个免费帐户。
- Azure Cloud Shell 预先安装了所有的先决条件。 更多内容请参阅《Azure Cloud Shell 快速入门》。
- 如果在本地(而不是使用 Azure Cloud Shell)中运行本指南中的命令,请完成以下步骤:
- 适用于 Unix 类环境的 Azure CLI。 本文仅需要 Azure CLI 的 Bash 环境。
- 本文需要的 Azure CLI 最低版本为 2.31.0。 如果你使用的是 Azure Cloud Shell,则表示已安装最新版本。
创建应用项目
使用以下命令克隆本文的示例 Java 项目。 该示例位于 GitHub 上。
git clone https://github.com/Azure-Samples/quarkus-azure
cd quarkus-azure
git checkout 2023-09-13
cd aca-quarkus
如果看到有关处于拆离的 HEAD 状态的消息,可以放心忽略此消息。 由于本文不需要任何提交,因此拆离的 HEAD 状态是合适的。
在本地测试 Quarkus 应用
本部分的步骤介绍如何在本地运行应用。
Quarkus 支持在开发和测试模式下自动预配未配置的服务。 Quarkus 将此功能称为开发服务。 假设你有 Quarkus 功能,例如连接到数据库服务。 你想要测试应用,但尚未完全配置与真实数据库的连接。 Quarkus 会自动启动相关服务的存根版本,并将应用程序连接到该服务。 更多信息请参阅 Quarkus 文档中的《开发服务概述》 。
请确保容器环境(Docker 或 Podman)正在运行,并使用以下命令进入 Quarkus 开发模式:
quarkus dev
使用 mvn quarkus:dev
取代 quarkus dev
通过 Maven 完成相同的操作。
系统可能会询问是否要发送 Quarkus 开发模式使用情况的遥测数据。 如果询问,请根据需要回答。
Quarkus 开发模式支持实时重载和后台编译。 对应用源代码进行任何修改后,刷新浏览器就可以看到更改。 错误页会显示任何编译或部署问题。 Quarkus 开发模式在 5005 端口上侦听调试程序。 如果要在运行之前等待附加调试程序,请在命令行输入 -Dsuspend
。 如果根本不需要调试器,可以使用 -Ddebug=false
。
输出应如以下示例所示:
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
INFO [io.quarkus] (Quarkus Main Thread) quarkus-todo-demo-app-aca 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.2.0.Final) started in 14.826s. Listening on: http://localhost:8080
INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
INFO [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-validator, jdbc-postgresql, narayana-jta, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]
--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
在运行 Quarkus 开发模式的终端上按 w 键。 w 键将打开默认 Web 浏览器并显示 Todo
应用程序。 还可以直接在 http://localhost:8080
访问应用程序 GUI。
请尝试在待办事项列表中选择待办事项。 UI 用删除线文本样式提示选择。 还可以通过键入“验证待办事项应用”并按 ENTER 键将新的待办事项添加到待办事项列表,如以下屏幕截图所示:
访问 RESTful API (/api
) 以获取存储在本地 PostgreSQL 数据库中的所有待办事项:
curl --verbose http://localhost:8080/api | jq .
输出应如以下示例所示:
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /api HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 664
< Content-Type: application/json;charset=UTF-8
<
{ [664 bytes data]
100 664 100 664 0 0 13278 0 --:--:-- --:--:-- --:--:-- 15441
* Connection #0 to host localhost left intact
[
{
"id": 1,
"title": "Introduction to Quarkus Todo App",
"completed": false,
"order": 0,
"url": null
},
{
"id": 2,
"title": "Quarkus on Azure App Service",
"completed": false,
"order": 1,
"url": "https://learn.microsoft.com/en-us/azure/developer/java/eclipse-microprofile/deploy-microprofile-quarkus-java-app-with-maven-plugin"
},
{
"id": 3,
"title": "Quarkus on Azure Container Apps",
"completed": false,
"order": 2,
"url": "https://learn.microsoft.com/en-us/training/modules/deploy-java-quarkus-azure-container-app-postgres/"
},
{
"id": 4,
"title": "Quarkus on Azure Functions",
"completed": false,
"order": 3,
"url": "https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-quarkus"
},
{
"id": 5,
"title": "Verify Todo apps",
"completed": false,
"order": 5,
"url": null
}
]
按 q 键退出 Quarkus 开发模式。
创建 Azure 资源以运行 Quarkus 应用
本部分的步骤介绍如何创建以下 Azure 资源来运行 Quarkus 示例应用:
- Microsoft Azure Database for PostgreSQL
- Microsoft Azure 容器注册表
- 容器应用
其中一些资源必须在 Azure 订阅范围内具有唯一的名称。 若要确保这种唯一性,可以使用首字母缩写、序列、日期、后缀模式。 若要应用此模式,请通过首字母缩写、序列号、当日日期和特定资源后缀来命名资源,例如,rg
表示“资源组”。 使用以下命令定义环境变量,以便稍后使用:
export UNIQUE_VALUE=<your unique value, such as ejb091223>
export RESOURCE_GROUP_NAME=${UNIQUE_VALUE}rg
export LOCATION=<your desired Azure region for deploying your resources. For example, eastus>
export REGISTRY_NAME=${UNIQUE_VALUE}reg
export DB_SERVER_NAME=${UNIQUE_VALUE}db
export DB_PASSWORD=Secret123456
export ACA_ENV=${UNIQUE_VALUE}env
export ACA_NAME=${UNIQUE_VALUE}aca
创建用于 PostgreSQL 的 Azure 数据库
Azure Database for PostgreSQL 是一种托管服务,可在 Azure 云中运行、管理和缩放具有高可用性的 PostgreSQL 数据库。 本部分导向单独的快速入门,介绍如何创建单个 Azure Database for PostgreSQL 服务器并与其连接。 但是,按照快速入门中的步骤操作时,需要使用下表中的设置来自定义示例 Quarkus 应用的数据库部署。 填写 Azure 门户中的字段时,请将环境变量替换为实际值。
设置 | 值 | 说明 |
---|---|---|
资源组 | ${RESOURCE_GROUP_NAME} |
选择“新建”。 部署会创建该新资源组。 |
服务器名称 | ${DB_SERVER_NAME} |
此值构成数据库服务器主机名的一部分。 |
位置 | ${LOCATION} |
从下拉列表中选择一个位置。 请记下位置。 其他创建的 Azure 资源必须使用此相同位置。 |
管理员用户名 | quarkus | 示例代码假定使用此值。 |
密码 | ${DB_PASSWORD} |
密码必须至少为 8 个字符,最多 128 个字符。 密码必须含以下字符类别中的三类 – 英文大写字母、英文小写字母、数字(0-9)及非字母数字字符(!、$、#、% 等)。 密码不能包含登录名的所有或部分。 登录名称的一部分定义为三个或多个连续字母数字字符。 |
脑中记得替换这些数据,同时请按照《快速入门:使用Azure 门户创建 Azure Database for PostgreSQL 服务器》中的步骤操作,直到“配置防火墙规则”部分。 然后,在“配置防火墙规则”部分中,确保为“允许访问 Azure 服务”选择“是”,然后选择“保存”。 如果忽略此操作,Quarkus 应用则无法访问数据库,并且根本无法启动。
完成“配置防火墙规则”部分的所有快速入门步骤(包括允许访问 Azure 服务的步骤)后,请返回到本文。
在 Azure Database for PostgreSQL 中创建 Todo 数据库
你在前面创建的 PostgreSQL 服务器为空。 没有任何可以与 Quarkus 应用程序配合使用的数据库。 使用以下命令创建名为 todo
的新数据库:
az postgres db create \
--resource-group ${RESOURCE_GROUP_NAME} \
--name todo \
--server-name ${DB_SERVER_NAME}
必须使用 todo
作为数据库的名称,因为示例代码假定使用此数据库名称。
如果命令成功,输出将类似于以下示例:
{
"charset": "UTF8",
"collation": "English_United States.1252",
"id": "/subscriptions/REDACTED/resourceGroups/ejb091223rg/providers/Microsoft.DBforPostgreSQL/servers/ejb091223db/databases/todo",
"name": "todo",
"resourceGroup": "ejb091223rg",
"type": "Microsoft.DBforPostgreSQL/servers/databases"
}
创建 Microsoft Azure 容器注册表实例
由于 Quarkus 是云原生技术,因此它内置支持创建在容器应用中运行的容器。 容器应用完全依赖于容器注册表,从中查找要运行的容器映像。 容器应用内置支持 Azure 容器注册表。
使用 az acr create 命令创建容器注册表实例。 以下示例创建名为环境变量值的 ${REGISTRY_NAME}
n 个容器注册表实例:
az acr create \
--resource-group $RESOURCE_GROUP_NAME \
--location ${LOCATION} \
--name $REGISTRY_NAME \
--sku Basic \
--admin-enabled
很快,你应该会在 JSON 输出中看到以下行:
"provisioningState": "Succeeded",
"publicNetworkAccess": "Enabled",
"resourceGroup": "<YOUR_RESOURCE_GROUP>",
将 docker 连接到容器注册表实例
登录到容器注册表实例。 登录后可以推送映像。 运行以下命令验证连接:
export LOGIN_SERVER=$(az acr show \
--name $REGISTRY_NAME \
--query 'loginServer' \
--output tsv)
echo $LOGIN_SERVER
export USER_NAME=$(az acr credential show \
--name $REGISTRY_NAME \
--query 'username' \
--output tsv)
echo $USER_NAME
export PASSWORD=$(az acr credential show \
--name $REGISTRY_NAME \
--query 'passwords[0].value' \
--output tsv)
echo $PASSWORD
docker login $LOGIN_SERVER -u $USER_NAME -p $PASSWORD
如果使用 Podman 而不是 Docker,请对命令进行必要的更改。
如果已成功登录到容器注册表实例,则应在命令输出末尾看到 Login Succeeded
。
创建环境
Azure 容器应用中的环境围绕一组容器应用创建安全边界。 部署到相同环境的容器应用部署在同一虚拟网络中,并将日志写入同一个 Log Analytics 工作区。 使用 az containerapp env create 命令创建环境,如以下示例所示:
az containerapp env create \
--resource-group $RESOURCE_GROUP_NAME \
--location $LOCATION \
--name $ACA_ENV
如果系统要求你安装扩展,请回答 Y。
自定义云原生配置
作为云原生技术,Quarkus 提供自动生成容器映像的功能。 有关详细信息,请参阅 容器映像。 然后,开发人员可以将应用程序映像部署到目标容器化平台,例如 Azure 容器应用。
若要生成容器映像,请使用以下命令在本地 container-image-jib
终端中添加扩展:
quarkus ext add container-image-jib
Quarkus 修改 POM,以确保扩展包含在其中 <dependencies>
。 如果系统要求你安装一些调用 JBang
的内容,请回答 是 ,并允许安装它。
输出应如以下示例所示:
[SUCCESS] ✅ Extension io.quarkus:quarkus-container-image-jib has been installed
若要验证是否已添加扩展,可以运行 git diff
检查输出。
作为一项云原生技术,Quarkus 支持配置文件概念。 Quarkus 拥有以下三个内置的配置文件:
dev
- 在开发模式下激活。test
- 在运行测试时激活。prod
- 在开发或测试模式下未运行时的默认配置文件。
Quarkus 根据需要支持任意数量的命名配置文件。
本部分中的剩余步骤指导取消注释和自定义 src/main/resources/application.properties 文件中的值。 通过删除前导 # %prod.
,确保取消所有以 #
开头行的注释。
%prod.
前缀表明在 prod
配置文件中运行时这些属性处于活动状态。 有关配置文件的详细信息,请参阅Quarkus 文档。
自定义数据库配置
添加以下数据库配置变量。 分别将<DB_SERVER_NAME_VALUE>
值替换为环境变量<DB_PASSWORD_VALUE>
${DB_PASSWORD}
和环境变量的实际值${DB_SERVER_NAME}
。
# Database configurations
%prod.quarkus.datasource.db-kind=postgresql
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://<DB_SERVER_NAME_VALUE>.postgres.database.azure.com:5432/todo
%prod.quarkus.datasource.jdbc.driver=org.postgresql.Driver
%prod.quarkus.datasource.username=quarkus@<DB_SERVER_NAME_VALUE>
%prod.quarkus.datasource.password=<DB_PASSWORD_VALUE>
%prod.quarkus.hibernate-orm.database.generation=create
%prod.quarkus.hibernate-orm.sql-load-script=no-file
通常,你不希望删除数据库中保存的数据,并在生产环境中使用示例数据重新填充。 因此,可以看到指定的quarkus.hibernate-orm.database.generation
create
架构,以便应用在初始启动时仅创建架构。 此外,数据库不会预先填充任何示例数据,因为 hibernate-orm.sql-load-script
指定为 no-file
。 此设置与以前在本地开发模式下运行应用时不同。 开发模式下的quarkus.hibernate-orm.database.generation
hibernate-orm.sql-load-script
默认值以及drop-and-create
import.sql
分别表示应用始终删除并重新创建数据库架构,并加载 import.sql 中定义的数据。 import.sql 文件是 Quarkus 的便利工具。 如果 Quarkus jar 中存在 src/main/resources/import.sql 文件,并且属性值为 import.sql
,则此文件中的 hibernate-orm.sql-load-script
SQL DML 语句在应用的启动时执行。
自定义容器映像配置
作为一项云原生技术,Quarkus 支持生成与 Docker 和 Podman 兼容的 OCI 容器映像。 添加以下容器映像变量。 分别将 <LOGIN_SERVER_VALUE>
和 <USER_NAME_VALUE>
的值替换为 ${LOGIN_SERVER}
和 ${USER_NAME}
环境变量的实际值。
# Container Image Build
%prod.quarkus.container-image.build=true
%prod.quarkus.container-image.registry=<LOGIN_SERVER_VALUE>
%prod.quarkus.container-image.group=<USER_NAME_VALUE>
%prod.quarkus.container-image.name=todo-quarkus-aca
%prod.quarkus.container-image.tag=1.0
生成容器映像并将其推送到容器注册表
现在,运行以下命令以生成应用程序。 此命令使用 Jib 扩展生成容器映像。
quarkus build --no-tests
输出应 BUILD SUCCESS
结尾。
可以使用命令行podman
(CLI)验证容器映像是否也docker
生成。 输出与以下示例类似:
docker images | grep todo-quarkus-aca
<LOGIN_SERVER_VALUE>/<USER_NAME_VALUE>/todo-quarkus-aca 1.0 0804dfd834fd 2 minutes ago 402MB
使用以下命令将容器映像推送到容器注册表:
export TODO_QUARKUS_TAG=$(docker images | grep todo-quarkus-aca | head -n1 | cut -d " " -f1):1.0
echo ${TODO_QUARKUS_TAG}
docker push ${TODO_QUARKUS_TAG}
输出应类似于以下示例:
The push refers to repository [<LOGIN_SERVER_VALUE>/<USER_NAME_VALUE>/todo-quarkus-aca]
188a550fce3d: Pushed
4e3afea591e2: Pushed
1db0eba807a6: Pushed
c72d9ccda0b2: Pushed
d7819b8a2d18: Pushed
d0e5cba6b262: Pushed
e0bac91f0f10: Pushed
1.0: digest: sha256:f9ccb476e2388efa0dfdf817625a94f2247674148a69b7e4846793e63c8be994 size: 1789
将应用映像推送到容器注册表后,请使用以下命令创建容器应用实例,在从容器注册表拉取映像后运行该应用:
az containerapp create \
--resource-group $RESOURCE_GROUP_NAME \
--name $ACA_NAME \
--image $TODO_QUARKUS_TAG \
--environment $ACA_ENV \
--registry-server $LOGIN_SERVER \
--registry-username $USER_NAME \
--registry-password $PASSWORD \
--target-port 8080 \
--ingress 'external'
成功的输出是一个 JSON 对象,包括属性 "type": "Microsoft.App/containerApps"
。
使用以下命令获取访问 Todo 应用程序的完全限定 URL:
export QUARKUS_URL=https://$(az containerapp show \
--resource-group $RESOURCE_GROUP_NAME \
--name $ACA_NAME \
--query properties.configuration.ingress.fqdn -o tsv)
echo $QUARKUS_URL
为 ${QUARKUS_URL}
打开新的 Web 浏览器。 然后,添加一个文本内容为 Deployed the Todo app to Container Apps
的新待办事项。 选择此项可将其标记为已完成。
访问 RESTful API (/api
) 以获取存储在 Azure Database for PostgreSQL 中的所有待办事项,如以下示例所示:
curl --verbose -k ${QUARKUS_URL}/api | jq .
输出应如以下示例所示:
* Connected to <aca-name>.<random-id>.eastus.azurecontainerapps.io (20.231.235.79) port 443 (#0)
> GET /api HTTP/2
> Host: <aca-name>.<random-id>.eastus.azurecontainerapps.io
> user-agent: curl/7.88.1
> accept: */*
>
< HTTP/2 200
< content-length: 88
< content-type: application/json;charset=UTF-8
<
[
{
"id": 1,
"title": "Deployed the Todo app to Container Apps",
"completed": true,
"order": 1,
"url": null
}
]
使用 Azure Cloud Shell 验证数据库是否已更新
选择搜索框旁边的 Cloud Shell 图标(),在Azure 门户中打开 Azure Cloud Shell。
在本地运行以下命令,并将结果粘贴到 Azure Cloud Shell:
echo psql --host=${DB_SERVER_NAME}.postgres.database.azure.com --port=5432 --username=quarkus@${DB_SERVER_NAME} --dbname=todo
当系统询问密码时,请使用创建数据库时使用的值。
使用以下查询获取所有待办事项:
select * from todo;
输出应类似于以下示例,并且应包含和以上所示待办事项应用 GUI 中相同的项:
输入 \q 退出 psql
程序并返回到 Cloud Shell。
清理资源
若要避免 Azure 费用,应清除不需要的资源。 如果不再需要群集,请使用 az group delete 命令来删除资源组、容器服务、容器注册表和所有的相关资源。
git reset --hard
docker rmi ${TODO_QUARKUS_TAG}
az group delete --name $RESOURCE_GROUP_NAME --yes --no-wait
你可能还想用于 docker rmi
删除 postgres
Quarkus 开发模式生成的和 testcontainers
容器映像。
后续步骤
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈