共用方式為


在 Azure Container Apps 上使用 Quarkus 部署 Java 應用程式

本文說明如何使用簡單的 CRUD 應用程式,在 Microsoft Azure Container Apps 上快速部署 Red Hat Quarkus。 該應用程式是具有 JavaScript 前端和 REST 端點的「待辦事項清單」。 適用於 PostgreSQL 的 Azure 資料庫彈性伺服器提供應用程式的持續性層。 本文說明如何在本機測試應用程式,並將其部署至容器應用程式。

必要條件

  • Azure 訂用帳戶。 如果您沒有 Azure 訂用帳戶,請在開始前建立免費帳戶
  • 使用已安裝類似 Unix 的作業系統 (例如 Ubuntu、macOS 或 Windows 子系統 Linux 版) 準備本機電腦。
  • 安裝 Java SE 實作第 17 版或更新版本 - 例如,Microsoft OpenJDK 的組建
  • 安裝 Maven 3.9.8 版或更高版本。
  • 為您的作業系統安裝 DockerPodman
  • 安裝 jq
  • 安裝 cURL
  • 安裝 Quarkus CLI 3.12.1 版或更新版本。
  • 適用於 Unix 的 Azure CLI 環境。 本文只需要 Azure CLI 的 Bash 變體。
    • 安裝 Azure CLI,並使用 az login 命令以互動方式登入 Azure,再使用 DefaultAzureCredential 程式代碼。
      az login
      
    • 本文需要使用至少 Azure CLI 2.61.0 版。

建立應用程式專案

使用下列命令複製本文的範例 Java 專案。 此範例位於 GitHub 上。

git clone https://github.com/Azure-Samples/quarkus-azure
cd quarkus-azure
git checkout 2024-07-08
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 開發模式執行所在的終端上按下 ww 鍵會開啟預設網頁瀏覽器以顯示 Todo 應用程式。 您也可以直接在 http://localhost:8080 存取應用程式 GUI。

Todo 範例應用程式的螢幕擷取畫面。

請嘗試在待辦事項清單中選取一些待辦事項項目。 UI 會指出具有刪除線文字樣式的選取範圍。 您也可以輸入 Verify Todo apps 並按下 ENTER,將新的待辦事項項目新增至待辦事項清單,如下列螢幕擷取畫面所示:

已新增新項目之 Todo 範例應用程式的螢幕擷取畫面。

存取 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 範例應用程式:

  • 適用於 PostgreSQL 的 Azure 資料庫彈性伺服器
  • Azure Container Registry
  • Azure 容器應用程式

其中有些資源在 Azure 訂用帳戶的範圍內必須有唯一的名稱。 若要確保此唯一性,您可以使用縮寫、序列、日期、尾碼模式。 若要套用此模式,請列出您的縮寫、某些序號、今天的日期,以及某種資源特定的後綴來命名資源,例如, rg 「資源群組」。 下列環境變數會使用此模式。 將中的 UNIQUE_VALUE佔位元值取代為 您自己的 LOCATION DB_PASSWORD 值,並在終端機中執行命令。

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_NAME=demodb
export DB_ADMIN=demouser
export DB_PASSWORD='<your desired password for the database server - for example, Secret123456>'
export ACA_ENV=${UNIQUE_VALUE}env
export ACA_NAME=${UNIQUE_VALUE}aca

建立適用於 PostgreSQL 的 Azure 資料庫彈性伺服器

適用於 PostgreSQL 的 Azure 資料庫彈性伺服器是完全受控的資料庫服務,其設計目的是要在資料庫管理功能和設定方面提供更細微的控制和彈性。 這一節顯示如何使用 Azure CLI 建立適用於 PostgreSQL 的 Azure 資料庫彈性伺服器執行個體。 如需詳細資訊,請參閱快速入門:使用 Azure CLI 建立適用於 PostgreSQL 的 Azure 資料庫 - 彈性伺服器執行個體

首先,使用下列命令建立資源群組,以包含資料庫伺服器和其他資源:

az group create \
    --name $RESOURCE_GROUP_NAME \
    --location $LOCATION

接下來,使用下列命令建立適用於 PostgreSQL 的 Azure 資料庫彈性伺服器執行個體:

az postgres flexible-server create \
    --name $DB_SERVER_NAME \
    --resource-group $RESOURCE_GROUP_NAME \
    --admin-user $DB_ADMIN \
    --admin-password $DB_PASSWORD \
    --database-name $DB_NAME \
    --public-access 0.0.0.0 \
    --yes

建立伺服器、資料庫、系統管理員使用者和防火牆規則需要幾分鐘的時間。 如果該命令成功,輸出會類似下列範例:

{
  "connectionString": "postgresql://<DB_ADMIN>:<DB_PASSWORD>@<DB_SERVER_NAME>.postgres.database.azure.com/<DB_NAME>?sslmode=require",
  "databaseName": "<DB_NAME>",
  "firewallName": "AllowAllAzureServicesAndResourcesWithinAzureIps_2024-7-5_14-39-45",
  "host": "<DB_SERVER_NAME>.postgres.database.azure.com",
  "id": "/subscriptions/REDACTED/resourceGroups/<RESOURCE_GROUP_NAME>/providers/Microsoft.DBforPostgreSQL/flexibleServers/<DB_SERVER_NAME>",
  "location": "East US",
  "password": "<DB_PASSWORD>",
  "resourceGroup": "<RESOURCE_GROUP_NAME>",
  "skuname": "Standard_D2s_v3",
  "username": "<DB_ADMIN>",
  "version": "13"
}

建立 Microsoft Azure Container Registry 執行個體

由於 Quarkus 是雲端原生技術,因此內建支援建立在 Container Apps 中執行的容器。 容器應用程式完全相依於容器登錄,它會從中尋找要執行的容器映像。 Container Apps 有 Azure Container Registry 的內建支援。

使用 az acr create 命令來建立 Container Registry 實例。 下列範例會使用環境變數 ${REGISTRY_NAME}的值,建立名為 的 n Container Registry 實例:

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 連線到 Container Registry 實例

登入 Container Registry 實例。 登入可讓您推送映像。 執行下列命令來驗證連線:

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,請對命令進行必要的變更。

如果您已成功登入 Container Registry 實例,您應該會在命令輸出結尾看到 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 Apps。

若要產生容器映像,請使用下列命令在本機終端機中新增 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 文件

檢查資料庫組態

新增下列資料庫組態變數。 資料庫連線相關屬性 %prod.quarkus.datasource.jdbc.url%prod.quarkus.datasource.username%prod.quarkus.datasource.password 會刻意保留空白,因為它們在運行時間是由 Azure Container Apps 環境基於安全性考慮提供。

# Database configurations
%prod.quarkus.datasource.db-kind=postgresql
%prod.quarkus.datasource.jdbc.driver=org.postgresql.Driver
%prod.quarkus.datasource.jdbc.url=
%prod.quarkus.datasource.username=
%prod.quarkus.datasource.password=
%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中的預設值分別是 drop-and-createimport.sql ,這表示應用程式一律會卸除並重新建立資料庫架構,並載入import.sql定義的hibernate-orm.sql-load-script數據。 import.sql檔案是Quarkus的便利設施。 如果 Quarkus jar 中有 src/main/resources/import.sql 檔案,且 屬性的值hibernate-orm.sql-load-scriptimport.sql,則此檔案中的 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

建置容器映像並將其推送至 Container Registry

現在,使用下列命令建置應用程式本身。 此命令會使用 Jib 擴充功能來建置容器映像。

quarkus build --no-tests

輸出應該以 BUILD SUCCESS 結尾。

您也可以使用 dockerpodman 命令列 (CLI) 來驗證容器映像是否也產生。 輸出會看似像以下範例:

docker images | grep todo-quarkus-aca
<LOGIN_SERVER_VALUE>/<USER_NAME_VALUE>/todo-quarkus-aca   1.0       0804dfd834fd   2 minutes ago   407MB

使用下列命令將容器映射推送至 Container Registry:

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

既然您已將應用程式映射推送至 Container Registry,請使用下列命令建立 Container Apps 實例,以在從 Container Registry 提取映射之後執行應用程式:

export DATASOURCE_JDBC_URL=jdbc:postgresql://${DB_SERVER_NAME}.postgres.database.azure.com:5432/${DB_NAME}?sslmode=require
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 \
    --secrets \
        jdbcurl=${DATASOURCE_JDBC_URL} \
        dbusername=${DB_ADMIN} \
        dbpassword=${DB_PASSWORD} \
    --env-vars \
        QUARKUS_DATASOURCE_JDBC_URL=secretref:jdbcurl \
        QUARKUS_DATASOURCE_USERNAME=secretref:dbusername \
        QUARKUS_DATASOURCE_PASSWORD=secretref:dbpassword \
    --ingress 'external'

選項 --secrets 可用來建立資料庫連接相關環境變數 QUARKUS_DATASOURCE_JDBC_URLQUARKUS_DATASOURCE_USERNAME QUARKUS_DATASOURCE_PASSWORD所參考的秘密。 這些環境變數的值會傳遞至 屬性 %prod.quarkus.datasource.password與屬性與屬性 。 %prod.quarkus.datasource.username %prod.quarkus.datasource.password Quarkus 知道在檔案中 application.properties 沒有值時,從對應的環境變數查閱值。

成功的輸出是 JSON 物件,包括 屬性 "type": "Microsoft.App/containerApps"

使用下列指令取得完整網址以存取 Todo 應用程式:

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} 的值。 然後,使用文字 Deployed the Todo app to Container Apps 新增待辦事項項目。 選取此專案將它標示為已完成。

在容器應用程式中執行的 Todo 範例應用程式的螢幕快照。

存取 RESTful API (/api) 以取得儲存在 適用於 PostgreSQL 的 Azure 資料庫 中的所有 todo 專案,如下列範例所示:

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=${DB_ADMIN} --dbname=${DB_NAME}

系統詢問密碼時,請使用您在建立資料庫時使用的值。

使用下列查詢來取得全部待辦事項項目:

select * from todo;

輸出看起來應該類似下列範例,而且應該在先前顯示的待辦事項應用程式 GUI 中包含相同的項目:

ASCII 資料表形式的查詢輸出螢幕擷取畫面。

輸入 \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 容器映射。

下一步