在本教學課程系列的這一部分中,您會瞭解如何將容器化的 Python Web 應用程式部署至 適用於容器的 Azure App Service Web 應用程式。 此完全受控的服務可讓您執行容器化應用程式,而不需要維護自己的容器協調器。
App Service 透過使用 Docker Hub、Azure Container Registry、Azure Key Vault 和其他 DevOps 工具的持續整合/持續部署 (CI/CD) 管線來簡化部署。 本教學課程是 5 部分教學課程系列的第 4 部分。
在這篇文章結束時,您將擁有一個從 Docker 容器映像執行的安全且可用於生產的 App Service Web 應用程式。 應用程式會使用 系統指派的受控識別 ,從 Azure Container Registry 提取映射,並從 Azure Key Vault 擷取秘密。
此服務圖表會醒目提示本文所涵蓋的元件。
Azure CLI 命令可以在 Azure Cloud Shell 或 已安裝 Azure CLI 的本機電腦上執行。
重要
建議您針對本教學課程中的所有 CLI 型步驟使用 Azure Cloud Shell ,因為它:
- 已預先向 Azure 帳戶進行驗證,以避免登入問題
- 包含所有必要的 Azure CLI 擴充功能
- 無論您的本機 OS 或環境為何,確保一致的行為
- 不需要本機安裝,非常適合沒有系統管理員許可權的使用者
- 從入口網站直接存取 Azure 服務,不需要本機 Docker 或網路設定
- 避免本機防火牆或網路設定問題
使用 RBAC 授權建立 Key Vault
Azure Key Vault 是用來儲存秘密、API 金鑰、連接字串和憑證的安全服務。 在這裡文稿中,它會儲存 MongoDB 連接字串 與 Web 應用程式的 SECRET_KEY
。
Key Vault 設定為使用 角色型訪問控制 (RBAC) 來管理透過 Azure 角色的存取,而不是傳統存取原則。 Web 應用程式會使用其 系統指派的受控識別 ,在運行時間安全地擷取秘密。
注意
儘早建立 Key Vault 可確保可以在任何嘗試存取秘密之前指派角色。 它也有助於避免角色指派的傳播延遲。 由於 Key Vault 並不相依於 App Service,因此布建它可提早改善可靠性和排序。
在此步驟中,您會使用 az keyvault create 命令來建立已啟用 RBAC 的 Azure Key Vault。
#!/bin/bash RESOURCE_GROUP_NAME="msdocs-web-app-rg" LOCATION="westus" KEYVAULT_NAME="${RESOURCE_GROUP_NAME}-kv" az keyvault create \ --name "$KEYVAULT_NAME" \ --resource-group "$RESOURCE_GROUP_NAME" \ --location "$LOCATION" \ --enable-rbac-authorization true
建立 App Service 方案和 Web 應用程式
App Service 方案會定義 Web 應用程式的計算資源、定價層和區域。 Web 應用程式會執行您的容器化應用程式,並使用系統指派的受控識別布建,用來安全地向 Azure Container Registry (ACR) 和 Azure Key Vault 進行驗證。
在此步驟中,您會執行下列工作:
- 建立 App Service 方案
- 使用其受控識別建立 Web 應用程式
- 設定 Web 應用程式以使用特定容器映像進行部署
- 透過 ACR 準備持續部署
注意
必須先建立 Web 應用程式,才能將存取權指派給 ACR 或 Key Vault,因為 受控識別只會在部署時建立。 此外,在建立時指定容器映像可確保應用程式按照預期的配置正確啟動。
在此步驟中,您會使用 az appservice plan create 命令來布建應用程式的計算環境。
#!/bin/bash APP_SERVICE_PLAN_NAME="msdocs-web-app-plan" az appservice plan create \ --name "$APP_SERVICE_PLAN_NAME" \ --resource-group "$RESOURCE_GROUP_NAME" \ --sku B1 \ --is-linux
在此步驟中,您會使用 az webapp create 命令來建立 Web 應用程式。 此命令也會啟用 系統指派的受控識別 ,並設定應用程式執行的容器映像。
#!/bin/bash APP_SERVICE_NAME="msdocs-website-name" #APP_SERVICE_NAME must be globally unique as it becomes the website name in the URL `https://<website-name>.azurewebsites.net`. # Use the same registry name as in part 2 of this tutorial series. REGISTRY_NAME="msdocscontainerregistryname" #REGISTRY_NAME is the registry name you used in part 2 of this tutorial. CONTAINER_NAME="$REGISTRY_NAME.azurecr.io/msdocspythoncontainerwebapp:latest" #CONTAINER_NAME is of the form "yourregistryname.azurecr.io/repo_name:tag". az webapp create \ --resource-group "$RESOURCE_GROUP_NAME" \ --plan "$APP_SERVICE_PLAN_NAME" \ --name "$APP_SERVICE_NAME" \ --assign-identity '[system]' \ --deployment-container-image-name "$CONTAINER_NAME"
注意
執行此指令時,您可能會看到下列錯誤:
No credential was provided to access Azure Container Registry. Trying to look up... Retrieving credentials failed with an exception:'Failed to retrieve container registry credentials. Please either provide the credentials or run 'az acr update -n msdocscontainerregistryname --admin-enabled true' to enable admin first.'
之所以發生此錯誤,是因為 Web 應用程式嘗試使用系統管理員認證來存取 ACR,預設會停用哪些認證。 可以放心地忽略此訊息:下一個步驟會設定 Web 應用程式使用其受控識別向 ACR 進行驗證。
將機密管理員角色授與已登入使用者
若要將秘密儲存在 Azure Key Vault 中,執行腳本的用戶必須具有 Key Vault 秘密官員 角色。 此角色允許在保存庫中建立和管理秘密。
在此步驟中,腳本會將該角色指派給目前登入的使用者。 然後,此使用者可以安全地儲存應用程式秘密,例如 MongoDB 連接字串與應用程式的 SECRET_KEY
。
此角色指派是兩個 Key Vault 相關角色指派中的第一個。 之後,Web 應用程式的系統指定的受控身份會獲得從保管庫擷取機密的存取權。
使用 Azure RBAC 可確保以身分識別為基礎的安全、可稽核的存取權,而不需要硬式編碼的認證。
注意
用戶必須先獲指派 Key Vault 秘密人員 角色, 才能 嘗試將任何秘密儲存在密鑰保存庫中。 此指派是使用限定於 Key Vault 的 az role assignment create 命令來完成。
在此步驟中,您會使用 az role assignment create 命令在 Key Vault 範圍中指派角色。
#!/bin/bash CALLER_ID=$(az ad signed-in-user show --query id -o tsv) echo $CALLER_ID # Verify this value retrieved successfully. In production, poll to verify this value is retrieved successfully. az role assignment create \ --role "Key Vault Secrets Officer" \ --assignee "$CALLER_ID" \ --scope "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME"
使用受控識別授與 ACR 的 Web 存取權
若要安全地從 Azure Container Registry (ACR) 提取映像,Web 應用程式必須設定為使用其 系統指派的受控識別。 使用受控識別可避免需要系統管理員認證,並支援安全、無認證的部署。
此程式牽涉到兩個主要動作:
- 讓 Web 應用程式在存取 ACR 時使用其受控識別
- 將 AcrPull 角色指派至目標 ACR 的該身分識別上
在此步驟中,您會使用 az webapp identity show 命令擷取 Web 應用程式受控識別的主體標識碼(唯一物件標識符)。 接下來,您會使用
acrUseManagedIdentityCreds
將 屬性true
設定為 ,以啟用使用 ACR 驗證的受控識別。 然後使用 az role assignment create 命令,將 AcrPull 角色指派給 Web 應用程式的受控識別。 此角色會授與 Web 應用程式從登錄提取映像的許可權。#!/bin/bash PRINCIPAL_ID=$(az webapp identity show \ --name "$APP_SERVICE_NAME" \ --resource-group "$RESOURCE_GROUP_NAME" \ --query principalId \ -o tsv) echo $PRINCIPAL_ID # Verify this value retrieved successfully. In production, poll for successful 'AcrPull' role assignment using `az role assignment list`. az webapp config set \ --resource-group "$RESOURCE_GROUP_NAME" \ --name "$APP_SERVICE_NAME" \ --generic-configurations '{"acrUseManagedIdentityCreds": true}' az role assignment create \ --role "AcrPull" \ --assignee "$PRINCIPAL_ID" \ --scope "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.ContainerRegistry/registries/$REGISTRY_NAME"
將金鑰保存庫存取權授予 Web 應用程式的受控身分識別
Web 應用程式需要許可權才能存取 MongoDB 連接字串和 SECRET_KEY
等秘密。 若要授與這些許可權,您必須將 Key Vault秘密使用者 角色指派給 Web 應用程式的 系統指派受控識別。
在此步驟中,您會使用 Web 應用程式系統指派受控識別的唯一標識碼(主體標識符),運用 az role assignment create 命令,授予該 Web 應用程式對金鑰保存庫中Key Vault Secrets User 角色的存取權。
#!/bin/bash az role assignment create \ --role "Key Vault Secrets User" \ --assignee "$PRINCIPAL_ID" \ --scope "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME"
將秘密儲存在 Key Vault 中
為了避免應用程式中的硬式編碼秘密,此步驟會將 MongoDB 連接字串 和 Web 應用程式的 秘密密鑰 儲存在 Azure Key Vault 中。 然後,Web 應用程式可以透過其受控識別安全地存取這些秘密,而不需要將認證儲存在程式代碼或設定中。
注意
雖然本教學課程只會將連接字串和秘密金鑰儲存在金鑰保存庫中,但您也可以選擇性地儲存其他應用程式設定,例如 Key Vault 中的 MongoDB 資料庫名稱或集合名稱。
在此步驟中,您會使用 az cosmosdb keys list 命令來擷取 MongoDB 連接字串。 然後使用 az keyvault secret set 命令,將連接字串和隨機產生的秘密密鑰儲存在 Key Vault 中。
#!/bin/bash ACCOUNT_NAME="msdocs-cosmos-db-account-name" MONGO_CONNECTION_STRING=$(az cosmosdb keys list \ --name "$ACCOUNT_NAME" \ --resource-group "$RESOURCE_GROUP_NAME" \ --type connection-strings \ --query "connectionStrings[?description=='Primary MongoDB Connection String'].connectionString" -o tsv) SECRET_KEY=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9') # This key is cryptographically secure, using OpenSSL’s strong random number generator. az keyvault secret set \ --vault-name "$KEYVAULT_NAME" \ --name "MongoConnectionString" \ --value "$MONGO_CONNECTION_STRING" az keyvault secret set \ --vault-name "$KEYVAULT_NAME" \ --name "MongoSecretKey" \ --value "$SECRET_KEY"
設定 Web 應用以使用 Kay Vault 秘密
若要在運行時間安全地存取秘密,必須將 Web 應用程式設定為參考儲存在 Azure Key Vault 中的秘密。 此步驟是使用 Key Vault 參考來完成,它會透過其 系統指派的受控識別,將秘密值插入應用程式的環境中。
此方法可避免硬式編碼秘密,並允許應用程式在執行期間安全地擷取敏感性值,例如 MongoDB 連接字串和秘密密鑰。
在此步驟中,您會使用 az webapp config appsettings set 命令來新增參考 Key Vault 秘密的應用程式設定。 具體而言,這會設定
MongoConnectionString
和MongoSecretKey
應用程式設定,以參考儲存在 Key Vault 中的對應秘密。#!/bin/bash MONGODB_NAME="restaurants_reviews" MONGODB_COLLECTION_NAME="restaurants_reviews" az webapp config appsettings set \ --resource-group "$RESOURCE_GROUP_NAME" \ --name "$APP_SERVICE_NAME" \ --settings \ CONNECTION_STRING="@Microsoft.KeyVault(SecretUri=https://$KEYVAULT_NAME.vault.azure.net/secrets/MongoConnectionString)" \ SECRET_KEY="@Microsoft.KeyVault(SecretUri=https://$KEYVAULT_NAME.vault.azure.net/secrets/MongoSecretKey)" \ DB_NAME="$MONGODB_NAME" \ COLLECTION_NAME="$MONGODB_COLLECTION_NAME"
從 ACR 啟動持續部署
啟用持續部署可讓 Web 應用程式在推送至 Azure Container Registry (ACR) 時自動提取並執行最新的容器映像。 這可減少手動部署步驟,並協助確保您的應用程式保持最新狀態。
注意
在下一個步驟中,您會在 ACR 中註冊 Webhook,以在推送新映像時通知 Web 應用程式。
在此步驟中,您會使用 az webapp deployment container config 命令來啟用從 ACR 到 Web 應用程式的連續部署。
#!/bin/bash az webapp deployment container config \ --name "$APP_SERVICE_NAME" \ --resource-group "$RESOURCE_GROUP_NAME" \ --enable-cd true
註冊 ACR Webhook 以進行持續部署
若要自動化部署,請在 Azure Container Registry (ACR) 中註冊 Webhook,以在推送新的容器映射時通知 Web 應用程式。 Webhook 可讓應用程式自動提取並執行最新版本。
在 Azure Container Registry 中設定的 Webhook 會在每當將新映射推送至 msdocspythoncontainerwebapp 存放庫時,就會將 POST 要求傳送至 Web 應用程式的 SCM 端點 (SERVICE_URI)。 此動作會觸發 Web 應用程式來提取和部署更新的映像,並完成 ACR 與 Azure App Service 之間的持續部署管線。
注意
Webhook URI 必須遵循下列格式:
https://<app-name>.scm.azurewebsites.net/api/registry/webhook
它必須以/api/registry/webhook
結尾。 如果您收到 URI 錯誤,請確認路徑正確無誤。
在此步驟中,使用 az acr webhook create 命令來註冊 webhook,並將其設定為在
push
事件上觸發。#!/bin/bash CREDENTIAL=$(az webapp deployment list-publishing-credentials \ --resource-group "$RESOURCE_GROUP_NAME" \ --name "$APP_SERVICE_NAME" \ --query publishingPassword --output tsv) # Web app publishing credentials may not be available immediately. In production, poll until non-empty. SERVICE_URI="https://$APP_SERVICE_NAME:$CREDENTIAL@$APP_SERVICE_NAME.scm.azurewebsites.net/api/registry/webhook" az acr webhook create \ --name webhookforwebapp \ --registry "$REGISTRY_NAME" \ --scope msdocspythoncontainerwebapp:* \ --uri "$SERVICE_URI" \ --actions push
瀏覽網站
若要確認 Web 應用程式正在執行,請開啟 https://<website-name>.azurewebsites.net
,並將 取代 <website-name>
為 App Service 的名稱。 您應該會看到餐廳檢閱範例應用程式。 第一次載入可能需要一些時間。
網站出現后,請嘗試新增餐廳並提交評論,以確認應用程式正常運作。
注意
Cloud Shell 不支援 az webapp browse
命令。 如果您使用 Cloud Shell,請手動開啟瀏覽器並瀏覽至網站 URL。
如果您在本機使用 Azure CLI,您可以使用 az webapp browse 命令在預設瀏覽器中開啟網站:
az webapp browse --name $APP_SERVICE_NAME --resource-group $RESOURCE_GROUP_NAME
注意
Cloud Shell 不支援 az webapp browse
命令。 開啟瀏覽器視窗,然後瀏覽至該網站的網址。
部署疑難排解
如果您沒有看到範例應用程式,請嘗試下列步驟。
- 使用容器部署和 App Service,請始終在 Azure 入口網站中查看 部署中心 / 記錄 頁面。 確認容器已拉取並正在運行中。 容器的初始拉取和執行可能需要一些時間。
- 嘗試重新啟動App Service,並查看這是否解決了您的問題。
- 如果有程式設計錯誤,這些錯誤會顯示在應用程式記錄中。 在 App Service 的 Azure 入口網站頁面上,選取 [診斷並解決問題/應用程式記錄]。
- 範例應用程式依賴連線至適用於 MongoDB 的 Azure Cosmos DB。 確認 App Service 具有具有正確連線資訊的應用程式設定。
- 確認 App Service 已啟用受控識別,並用於部署中心。 在 App Service 的 Azure 入口網站頁面上,移至 App Service 部署中心 資源,並確認 驗證 已設定為 受控識別。
- 檢查是否已在 Azure Container Registry 中定義 Webhook。 Webhook 可讓 App Service 提取容器映像。 特別是,檢查服務 URI 是否以 “/api/registry/webhook” 結尾。 如果沒有,請加以新增。
- 不同的 Azure 容器註冊表 SKU 具有不同的功能,包括 Webhook 數目。 如果您要重複使用現有的登錄表冊,您可能會看到下列訊息:「針對登錄 SKU 基本的網路掛鉤資源類型超過配額。」 深入瞭解不同的 SKU 配額和升級程式:https://aka.ms/acr/tiers"。 如果您看到此訊息,請使用新的註冊表,或減少目前使用中的 註冊表 Webhook 數目。