在本教學課程系列的這一部分中,您會瞭解如何將容器化的 Python Web 應用程式部署至 適用於容器的 Azure App 服務 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 Cloud Shell 執行Azure CLI指令,或是在安裝了 Azure CLI 的本地機器上執行。
重要
在本教學中,所有基於 CLI 的步驟都使用 Azure Cloud Shell,因為它:
- 它會預先用 Azure 帳號認證,所以不會遇到認證問題
- 包含所有必要的 Azure CLI 擴充功能
- 無論您的本機 OS 或環境為何,確保一致的行為
- 不需要本機安裝,非常適合沒有系統管理員許可權的使用者
- 提供直接從入口網站存取 Azure 服務——不需要本地 Docker 或網路設定
- 避免本地防火牆或網路設定問題
使用 RBAC 授權建立 金鑰保存庫
Azure Key Vault 是用來儲存秘密、API 金鑰、連接字串和憑證的安全服務。 在這裡文稿中,它會儲存 MongoDB 連接字串 與 Web 應用程式的 SECRET_KEY。
將金鑰保存庫設定為使用 基於角色的存取控制(RBAC)來透過Azure角色管理存取,而非傳統的存取政策。 Web 應用程式會使用其 系統指派的受控識別 ,在運行時間安全地擷取秘密。
注意
要早點建立 金鑰保存庫,確保你能在嘗試存取秘密前就分配角色。 此方法也有助於避免角色分配的傳播延遲。 由於 金鑰保存庫 不依賴 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 應用程式的計算資源、定價層和區域。 這個網頁應用程式執行你的容器化應用程式,並以系統指派的管理身份來安全認證 Azure Container Registry(ACR)和 Azure Key Vault。
在此步驟中,請完成以下任務:
- 建立 App Service 方案
- 使用其受控識別建立 Web 應用程式
- 透過特定的容器映像設定網頁應用程式部署
- 透過 ACR 準備持續部署
注意
您必須先建立網頁應用程式,才能分配 ACR 或 金鑰保存庫 的存取權限,因為 managed 身份是在部署時 才建立的。 此外,在建立時指定容器映像可確保應用程式按照預期的配置正確啟動。
使用 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 指令來建立網頁應用程式。 此命令也會啟用 系統指派的受控識別 ,並設定應用程式執行的容器映像。
#!/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.'此錯誤發生是因為網頁應用程式嘗試使用管理員憑證存取 ACR,但管理員憑證預設是被停用的。 您可以放心忽略這個訊息。 下一步是設定網頁應用程式使用其管理身份與 ACR 進行認證。
將 金鑰保存庫 Secrets Officer 角色授與已驗證的使用者
若要將秘密儲存在 Azure Key Vault 中,執行腳本的用戶必須具有 金鑰保存庫 秘密官員 角色。 此角色授予在保存庫內建立及管理密碼的權限。
在此步驟中,腳本會將該角色指派給目前已認證的使用者。 然後,此使用者可以安全地儲存應用程式秘密,例如 MongoDB 連接字串與應用程式的 SECRET_KEY。
此角色指派是兩個 金鑰保存庫 相關角色指派中的第一個。 之後,Web 應用程式的系統指定的受控身份會獲得從保管庫擷取機密的存取權。
透過使用 Azure RBAC,您可以確保基於身份的存取安全且可稽核,因此不需要使用硬編碼的憑證。
注意
在使用者之前嘗試將任何祕密儲存在 金鑰保存庫 中之前,請將 金鑰保存庫 祕密管理員 角色指派給該使用者。 使用範圍限定於 金鑰保存庫 的 az role assignment create 命令來建立此指派。
使用 az 角色分配 create 指令,在 金鑰保存庫 範圍內指派該角色。
#!/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 應用程式在存取 ACR 時使用其受控識別
- 將 AcrPull 角色指派至目標 ACR 的該身分識別上
在此步驟中,透過使用 az webapp identity show 指令,取得網頁應用程式管理身份的主 ID(唯一物件 ID)。 接著,使用 az webapp config set,將
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等秘密。 要授予這些權限,請將 金鑰保存庫 秘密使用者 角色指派給網頁應用程式的 系統指派的管理身份 。
在此步驟中,使用 Web 應用程式系統指派受控識別的唯一識別碼(主體識別碼),透過 az role assignment create 命令,以 金鑰保存庫 Secrets User 角色授與 Web 應用程式存取 金鑰保存庫 的權限。
#!/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"
將機密存放在 金鑰保存庫 中
為了避免在應用程式中硬編碼祕密,請將
注意
雖然本教學課程只會將連接字串和秘密金鑰儲存在金鑰保存庫中,但您也可以選擇性地儲存其他應用程式設定,例如 金鑰保存庫 中的 MongoDB 資料庫名稱或集合名稱。
請使用 az cosmosdb keys list 指令來取得 MongoDB 連接字串。 接著,使用 az keyvault secret set 指令,將連接字串和隨機產生的秘密金鑰都儲存在 金鑰保存庫。
#!/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 應用程式以使用 金鑰保存庫 祕密
要在執行時安全存取秘密,請設定網頁應用程式參考 Azure Key Vault 中儲存的秘密。 使用 金鑰保存庫 參考,透過應用程式的 系統指派受控識別,將祕密值注入應用程式的環境中。
此方法可避免硬式編碼秘密,並允許應用程式在執行期間安全地擷取敏感性值,例如 MongoDB 連接字串和秘密密鑰。
使用 az webapp config appsettings set 指令來新增參考 金鑰保存庫 秘密的應用程式設定。 具體來說,請將
MongoConnectionString和MongoSecretKey應用程式設定為參考 金鑰保存庫 中儲存的對應秘密。#!/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 啟動持續部署
當你啟用持續部署時,網頁應用程式會自動拉取並執行最新的容器映像檔,當你推送到Azure Container Registry(ACR)時。 此功能減少手動部署步驟,並協助確保應用程式持續更新。
注意
下一步,你在 ACR 註冊一個 webhook,以便在推送新圖片時通知網頁應用程式。
使用 az webapp deployment container config 指令,啟用從 ACR 持續部署到網頁應用程式。
#!/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(ACR)會在每當有新映像檔推送到 msdocspythoncontainerwebapp 倉庫時,向網頁應用程式的 SCM 端點(SERVICE_URI)發送 POST 請求。 此動作會觸發 Web 應用程式來提取和部署更新的映像,並完成 ACR 與 Azure App 服務 之間的持續部署管線。
注意
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,請手動開啟瀏覽器並點到網站網址。
如果你是本地使用 Azure CLI,請使用 az webapp 瀏覽指令在預設瀏覽器中開啟該網站:
az webapp browse --name $APP_SERVICE_NAME --resource-group $RESOURCE_GROUP_NAME
注意
Cloud Shell 不支援 az webapp browse 命令。 打開瀏覽器視窗,然後直接點到網站網址。
部署疑難排解
如果您沒有看到範例應用程式,請嘗試下列步驟。
- 關於容器部署和 App Service,請務必在 Azure 入口網站查看 Deployment Center / Logs 頁面。 確認貨櫃已被拉出並運作。 容器的初始拉取和執行可能需要一些時間。
- 嘗試重新啟動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 數目。 如果你正在重複使用現有的登錄檔,可能會看到訊息:「資源類型 webhook 的配額超過 registry SKU Basic 的配置。 深入瞭解不同的 SKU 配額和升級程式:https://aka.ms/acr/tiers"。 如果您看到此訊息,請使用新的註冊表,或減少目前使用中的 註冊表 Webhook 數目。