本文是教學課程系列的一部分,說明如何將 Python Web 應用程式容器化和部署至 azure Container Apps
在本教學課程中,您會:
- 在雲端中建置容器映像,以容器化 Python 範例 Web 應用程式 (Django 或 Flask)。
- 將容器映像部署至 Azure Container Apps。
- 定義環境變數,讓容器應用程式能夠連線到 適用於PostgreSQL的 Azure 資料庫 - 彈性伺服器 實例,其中範例應用程式會儲存數據。
下圖醒目提示本教學課程中的工作:建置和部署容器映像。
先決條件
如果您沒有 Azure 訂用帳戶,請在開始之前建立 免費帳戶。
您可以在 Azure Cloud Shell 或已安裝 azure CLI 的工作站上執行 Azure CLI 命令。
如果您在本機執行,請遵循下列步驟來登入並安裝本教學課程的必要模組:
如有必要,請登入 Azure 並進行驗證:
az login
請確定您執行的是最新版的 Azure CLI:
az upgrade
使用 az extension add 命令,安裝或升級 containerapp 和 rdbms-connect 的 Azure CLI 擴充功能:
az extension add --name containerapp --upgrade az extension add --name rdbms-connect --upgrade
取得範例應用程式
將範例程式碼派生並克隆至您的開發環境:
移至範例應用程式的 GitHub 存放庫(Django 或 Flask),然後選取 [分支]。
請按照以下步驟將儲存庫分叉到你的 GitHub 帳戶中。 您也可以不需要復刻或 GitHub 帳戶,直接將代碼庫下載到本地電腦。 但是,如果您使用下載方法,您將無法在本系列下一個教學課程中設定持續整合和持續傳遞(CI/CD)。
在主控台的命令提示字元中,使用 git clone 命令將分支存放庫複製到 python-container 資料夾:
# Django git clone https://github.com/<github-username>/msdocs-python-django-azure-container-apps.git python-container # Flask # git clone https://github.com/<github-username>/msdocs-python-flask-azure-container-apps.git python-container
變更目錄:
cd python-container
從 Web 應用程式程式代碼建置容器映像
遵循這些步驟之後,您將有一個 Azure Container Registry 實例,其中包含從範例程式代碼建置的 Docker 容器映射。
如果您在 Windows 電腦上的 Git Bash 終端中執行命令,請在繼續之前輸入以下命令:
#!/bin/bash export MSYS_NO_PATHCONV=1
使用 az group create 命令 建立資源群組:
#!/bin/bash RESOURCE_GROUP_NAME=<resource-group-name> LOCATION=<location> az group create \ --name $RESOURCE_GROUP_NAME \ --location $LOCATION
使用命令 az acr create 來建立容器註冊表。
#!/bin/bash REGISTRY_NAME=<registry-name> #The name that you use for *\<registry-name>* must be unique within Azure, and it must contain 5 to 50 alphanumeric characters. az acr create \ --resource-group $RESOURCE_GROUP_NAME \ --name $REGISTRY_NAME \ --sku Basic \ --admin-enabled true
使用 az acr login 命令登入至登錄處。
az acr login --name $REGISTRY_NAME
命令會將 「azurecr.io」 新增至名稱,以建立完整登錄名稱。 如果登入成功,會出現「登入成功」訊息。 如果您要從不同於建立登錄的訂用帳戶來存取登錄,請使用
--suffix
開關。如果登入失敗,請確定 Docker 精靈正在您的系統上執行。
使用 az acr build 命令建置映像:
#!/bin/bash az acr build \ --registry $REGISTRY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --image pythoncontainer:latest .
這些考慮適用於:
命令結尾的點 (
.
) 表示要建置的原始碼位置。 如果您未在範例應用程式的根目錄中執行此命令,請指定程式代碼的路徑。如果您在 Azure Cloud Shell 中執行 命令,請使用
git clone
先將存放庫提取到 Cloud Shell 環境中。 然後將目錄切換到專案的根目錄,以便正確解釋點(.
)。如果您省略 [
-t
相同--image
] 選項,命令會將本機內容組建排入佇列,而不會將它推送至登錄。 在沒有推送的情況下建置對於檢查映像是否建置很有用。
使用 az acr repository list 命令確認容器映像已創建:
az acr repository list --name $REGISTRY_NAME
注意
本節中的步驟會在基本服務層級中建立容器登錄。 此層是成本優化的,擁有為開發人員的使用情境而設計的功能集和吞吐量,並且符合本教學課程需求。 在生產場景中,您很可能會使用標準或進階服務層級。 這些層級提供增強的儲存和吞吐量。
若要深入瞭解,請參閱 Azure Container Registry 服務層級。 如需定價資訊,請參閱 Azure Container Registry 定價。
建立 PostgreSQL 彈性伺服器實例
範例應用程式 (Django 或 Flask) 會將餐廳檢閱資料儲存在 PostgreSQL 資料庫中。 在這些步驟中,您會建立將包含資料庫的伺服器。
使用 az postgres flexible-server create 命令在 Azure 中建立 PostgreSQL 伺服器。 此命令在完成前執行幾分鐘並不罕見。
#!/bin/bash ADMIN_USERNAME=demoadmin ADMIN_PASSWORD=<admin-password> # Use a strong password that meets the requirements for PostgreSQL. POSTGRES_SERVER_NAME=<postgres-server-name> az postgres flexible-server create \ --resource-group $RESOURCE_GROUP_NAME \ --name $POSTGRES_SERVER_NAME \ --location $LOCATION \ --admin-user $ADMIN_USERNAME \ --admin-password $ADMIN_PASSWORD \ --version 16 \ --tier Burstable \ --sku-name Standard_B1ms \ --public-access 0.0.0.0 \ --microsoft-entra-auth Enabled \ --storage-size 32 \ --backup-retention 7 \ --high-availability Disabled \ --yes
使用這些值:
<postgres-server-name>:PostgreSQL 資料庫伺服器名稱。 此名稱在所有 Azure 中都必須是唯一的。 伺服器的端點是
https://<postgres-server-name>.postgres.database.azure.com
。 允許的字元是A
至Z
、0
至9
,以及連字號(-
)。<位置>:使用您用於 Web 應用程式的相同位置。 <位置> 是從命令
Name
的輸出中取得的 Azure 位置值az account list-locations -o table
之一。<admin-username>:系統管理員帳戶的用戶名稱。 它不能
azure_superuser
、admin
、administrator
、root
、guest
或public
。 請使用demoadmin
進行此教學。<系統管理員密碼>:系統管理員用戶的密碼。 其必須包含 8 到 128 個字元,且來自下列類別的其中三個類別:英文大寫字母、英文小寫字母、數字及非英數字元。
重要
當您建立使用者名稱或密碼時,不會 使用貨幣符號 ($) 字元。 稍後,當您使用這些值建立環境變數時,該字元在用來執行 Python 應用程式的 Linux 容器中具有特殊意義。
--version
:使用16
。 它會指定要用於伺服器的 PostgreSQL 版本。--tier
:使用Burstable
。 它會指定伺服器的定價層。 彈性階層是一個較低成本的選擇,適用於不需要持續使用全部 CPU 的工作負載,並適合本教學課程的需求。--sku-name
:定價層和計算組態的名稱;例如,Standard_B1ms
。 如需詳細資訊,請參閱適用於 PostgreSQL 的 Azure 資料庫定價。 若要列出可用的層,請使用az postgres flexible-server list-skus --location <location>
。--public-access
:使用0.0.0.0
。 它允許從任何 Azure 服務公開存取伺服器,例如 Container Apps。--microsoft-entra-auth
:使用Enabled
。 它會在伺服器上啟用Microsoft Entra 驗證。--storage-size
:使用32
。 它會指定伺服器以 GB 為單位的記憶體大小。 最小值為 32 GB。--backup-retention
:使用7
。 它會指定保留伺服器備份的天數。 最小值為 7 天。--high-availability
:使用Disabled
。 它會停用伺服器的高可用性。 本教學課程不需要高可用性。--yes
:它接受PostgreSQL伺服器的使用規定。
注意
如果您計劃從本機工作站使用工具來操作 PostgreSQL 伺服器,則需要使用 az postgres flexible-server firewall-rule create 命令,為本機工作站的 IP 位址新增防火牆規則。
使用 az ad signed-in-user show 命令來取得使用者帳戶的物件識別符。 您會在下一個命令中使用這個識別碼。
#!/bin/bash CALLER_OBJECT_ID=$(az ad signed-in-user show --query id -o tsv) CALLER_DISPLAY_NAME=$(az ad signed-in-user show --query userPrincipalName -o tsv)
使用 az postgres flexible-server ad-admin create 命令,將您的使用者帳戶新增為 PostgreSQL 伺服器上的 Microsoft Entra 系統管理員:
#!/bin/bash az postgres flexible-server microsoft-entra-admin create \ --server-name "$POSTGRES_SERVER_NAME" \ --resource-group "$RESOURCE_GROUP_NAME" \ --display-name "$CALLER_DISPLAY_NAME" \ --object-id "$CALLER_OBJECT_ID" \ --type User
使用 az postgres flexible-server firewall-rule create 命令來新增規則,讓您的 Web 應用程式能夠存取 PostgreSQL 彈性伺服器。 在下列命令中,您會使用公用IP位址,將伺服器的防火牆設定為接受來自開發工作站的連線:
MY_IP=$(curl -s ifconfig.me) az postgres flexible-server firewall-rule create \ --name "$POSTGRES_SERVER_NAME" \ --resource-group "$RESOURCE_GROUP_NAME" \ --rule-name allow-my-ip \ --start-ip-address "$MY_IP" \ --end-ip-address "$MY_IP" ```
注意
本節中的步驟會在高載定價層中建立具有單一虛擬核心和有限記憶體的 PostgreSQL 伺服器。 彈性階層是一個較低成本的選擇,適用於不需要持續使用全部 CPU 的工作負載,並適合本教學課程的需求。 針對生產工作負載,您可以升級至一般用途或記憶體優化定價層。 這些層級可提供更高的效能,但會增加成本。
若要深入瞭解,請參閱適用於 PostgreSQL 的 Azure 資料庫中 計算選項 - 彈性伺服器。 如需定價的相關信息,請參閱 Azure PostgreSQL 資料庫的定價。
在伺服器上建立資料庫
此時,您有 PostgreSQL 伺服器。 在本節中,您會在伺服器上建立資料庫。
使用 az postgres flexible-server db create 命令來建立名為 restaurants_reviews的資料庫:
#!/bin/bash
DATABASE_NAME=restaurants_reviews
az postgres flexible-server db create \
--resource-group $RESOURCE_GROUP_NAME \
--server-name $POSTGRES_SERVER_NAME \
--database-name $DATABASE_NAME
您也可以使用 az postgres flexible-server connect 命令來連線到資料庫,然後使用 psql 命令。 當您使用 psql 時,通常使用 Azure Cloud Shell 會更容易,因為這個 Shell 已經包含了所有所需的相依套件。
您也可以連線到適用於 PostgreSQL 的 Azure 資料庫彈性伺服器,並使用 psql 或支援 PostgreSQL 的 IDE 來建立資料庫,例如 Azure Data Studio。 如需使用 psql 的步驟,請參閱本文稍後的 在 PostgreSQL 資料庫上設定受控識別。
建立使用者指派的受控識別
建立使用者指派的受控識別,以在 Azure 中執行時作為容器應用程式的身分識別。
注意
若要建立使用者指派的受控識別,您的帳戶需要 受控識別提供者 角色指派。
使用 az identity create 命令來建立使用者指派的受控識別 (即受管理的身分識別):
UA_MANAGED_IDENTITY_NAME=<managed-identity-name> # Use a unique name for the managed identity, such as-"my-ua-managed-id".
az identity create \
--name $UA_MANAGED_IDENTITY_NAME
--resource-group $RESOURCE_GROUP_NAME
在 PostgreSQL 資料庫上設定受控識別
將受控識別設定為 PostgreSQL 伺服器上的角色,然後將 restaurants_reviews 資料庫的必要許可權授與它。 無論您是使用 Azure CLI 或 psql,您都必須使用已被設定為伺服器實例上 Microsoft Entra 系統管理員的使用者連線到 Azure PostgreSQL 伺服器。 只有配置為 PostgreSQL 系統管理員的 Microsoft Entra 帳戶,才能在您的伺服器上設定受控的身份和其他 Microsoft 系統管理員角色。
使用 az account get-access-token 命令來取得 Azure 帳戶的存取令牌。 您在後續步驟中使用存取令牌。
#!/bin/bash MY_ACCESS_TOKEN=$(az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken) echo $MY_ACCESS_TOKEN
使用 az postgres flexible-server execute 命令,將使用者指派的受控識別新增為您的 PostgreSQL 伺服器上的資料庫角色:
#!/bin/bash az postgres flexible-server execute \ --name "$POSTGRES_SERVER_NAME" \ --admin-user "$CALLER_DISPLAY_NAME" \ --admin-password "$ACCESS_TOKEN" \ --database-name postgres \ --querytext "SELECT * FROM pgaadauth_create_principal('$UA_MANAGED_IDENTITY_NAME', false, false);"
注意
如果您要在本機工作站上執行
az postgres flexible-server execute
命令,請確定您已為工作站的 IP 位址新增防火牆規則。 您可以使用 az postgres flexible-server firewall-rule create 命令來新增規則。 下一步中的命令也有相同的需求。使用下列 az postgres flexible-server execute 命令,將 restaurants_reviews 資料庫的必要許可權授與使用者指派的受控識別:
#!/bin/bash SQL_GRANTS=$(cat <<EOF GRANT CONNECT ON DATABASE $DATABASE_NAME TO "$UA_MANAGED_IDENTITY_NAME"; GRANT USAGE, CREATE ON SCHEMA public TO "$UA_MANAGED_IDENTITY_NAME"; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "$UA_MANAGED_IDENTITY_NAME"; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "$UA_MANAGED_IDENTITY_NAME"; EOF ) az postgres flexible-server execute \ --name "$POSTGRES_SERVER_NAME" \ --admin-user "$CALLER_DISPLAY_NAME" \ --admin-password "$MY_ACCESS_TOKEN" \ --database-name "$DATABASE_NAME" \ --querytext "$SQL_GRANTS"
此 Azure CLI 命令會連線到伺服器上的 restaurants_reviews 資料庫,併發出下列 SQL 命令:
GRANT CONNECT ON DATABASE restaurants_reviews TO "my-ua-managed-id"; GRANT USAGE ON SCHEMA public TO "my-ua-managed-id"; GRANT CREATE ON SCHEMA public TO "my-ua-managed-id"; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "my-ua-managed-id"; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "my-ua-managed-id";
將 Web 應用程式部署至容器應用程式
容器應用程式會部署至 Azure Container Apps 環境,其可作為安全界限。 在下列步驟中,您會先建立環境,然後在該環境中建立一個容器。 接著,您可以設定容器,讓網站在外部可見。
這些步驟需要 Azure Container Apps 擴充功能,containerapp。
使用 az containerapp env create 命令建立 Container Apps 環境:
#!/bin/bash APP_ENV_NAME=<app-env-name> # Use a unique name for the environment, such as "python-container-env". az containerapp env create \ --name python-container-env \ --resource-group $RESOURCE_GROUP_NAME \ --location $LOCATION
使用 az acr credential show 命令,取得 Azure Container Registry 實例的登入認證:
#!/bin/bash REGISTRY_CREDS=$(az acr credential show -n "$REGISTRY_NAME" --query "[username,passwords[0].value]" -o tsv) REGISTRY_USERNAME=$(echo "$REGISTRY_CREDS" | head -n1) REGISTRY_PASSWORD=$(echo "$REGISTRY_CREDS" | tail -n1)
當您在步驟 5 中建立容器應用程式時,您會使用命令輸出中傳回的使用者名稱和其中一個密碼。
使用 az identity show 命令來獲取用戶指派的受控識別的客戶端識別碼和資源識別碼:
UA_CLIENT_ID=$(az identity show \ --name "$UA_MANAGED_IDENTITY_NAME" \ --resource-group "$RESOURCE_GROUP" \ --query clientId -o tsv) UA_RESOURCE_ID=$(az identity show \ --name "$UA_MANAGED_IDENTITY_NAME" \ --resource-group "$RESOURCE_GROUP" \ --query id -o tsv)
當您在步驟 5 中建立容器應用程式時,您會使用命令輸出中的用戶端識別元 (GUID) 值和資源識別碼。 資源識別碼的格式如下:
/subscriptions/<subscription-id>/resourcegroups/pythoncontainer-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-ua-managed-id
。執行下列命令來產生秘密金鑰值:
AZURE_SECRET_KEY=$(python -c 'import secrets; print(secrets.token_hex())')
當您在步驟 5 中建立容器應用程式時,您可以使用秘密金鑰值來設定環境變數。
注意
此步驟顯示的命令適用於 Bash Shell。 視您的環境而定,您可能需要使用
python3
叫用 Python。 在 Windows 上,您必須以雙引弧括住-c
參數中的命令,而不是單引號。 視您的環境而定,您可能也需要使用py
或py -3
叫用 Python。在環境中使用 az containerapp create 命令建立容器應用程式。
az containerapp create \ --name "$CONTAINER_APP_NAME" \ --resource-group "$RESOURCE_GROUP" \ --environment "$APP_ENV" \ --image "$REGISTRY_NAME.azurecr.io/$IMAGE_NAME" \ --target-port "$TARGET_PORT" \ --ingress external \ --registry-server "$REGISTRY_NAME.azurecr.io" \ --registry-username "$REGISTRY_USERNAME" \ --registry-password "$REGISTRY_PASSWORD" \ --user-assigned "$UA_RESOURCE_ID" \ --env-vars \ DBHOST="$POSTGRES_SERVER_NAME" \ DBNAME="$DATABASE_NAME" \ DBUSER="$UA_MANAGED_IDENTITY_NAME" \ RUNNING_IN_PRODUCTION=1 \ AZURE_CLIENT_ID="$UA_CLIENT_ID" \ AZURE_SECRET_KEY="$AZURE_SECRET_KEY" ```
僅限 Django,請移轉並建立資料庫架構。 (在 Flask 範例應用程式中,它會自動完成,您可以略過此步驟。
使用 az containerapp exec 命令連線:
az containerapp exec \ --name $CONTAINER_APP_NAME \ --resource-group $RESOURCE_GROUP_NAME
然後,在shell指令提示字元中,輸入
python manage.py migrate
。您不需要移轉容器的修訂。
測試網站。
您先前輸入的
az containerapp create
命令將輸出一個應用程式網址,您可以用來訪問該應用程式。 URL 結尾為azurecontainerapps.io
。 在瀏覽器中打開該 URL。 或者,您可以使用 az containerapp browse 命令。
新增餐廳和兩個評論後,這是範例網站的一個示例。
針對部署進行疑難排解
您忘記應用程式 URL 來存取網站
在 Azure 入口網站中:
- 移至容器應用程式的 [概觀] 頁面,並尋找 應用程式 URL。
在 VS Code 中:
- 移至 Azure 檢視 (Ctrl+Shift+A),然後展開您正在使用的訂用帳戶。
- 展開 [Container Apps] 節點,展開受控環境,以滑鼠右鍵點擊 python-container-app,然後選取 [瀏覽]。 VS Code 會使用應用程式 URL 開啟瀏覽器。
在 Azure CLI 中:
- 使用命令
az containerapp show -g pythoncontainer-rg -n python-container-app --query properties.configuration.ingress.fqdn
。
在 VS Code 中,Azure 任務執行建置映像檔時會傳回錯誤
如果您看到「錯誤:無法下載內容」訊息。 請檢查 VS Code 輸出 視窗中的 URL 是否不正確,然後於 Docker 擴充功能中更新登錄。 若要重新整理,請選取 Docker 擴充功能,移至 登錄 區段,找到註冊表,然後選取它。
如果您在 Azure 工作中再次執行
在 Azure 入口網站中,建立容器應用程式期間會出現存取錯誤
在停用 Azure Container Registry 實例上的系統管理員認證時,會發生包含「無法存取 ACR '<名稱>.azurecr.io』」 的存取錯誤。
若要在入口網站中檢查系統管理員狀態,請移至您的 Azure Container Registry 實例,選取 存取密鑰 資源,並確定已啟用 系統管理員使用者。
您的容器映像不會出現在 Azure Container Registry 實例中
- 檢查 Azure CLI 命令或 VS Code 的輸出,並尋找訊息以確認成功。
- 使用 Azure CLI 或 VS Code 工作提示,檢查您的組建命令中已正確指定登錄的名稱。
- 請確定您的認證未過期。 例如,在 VS Code 中,在 Docker 擴充功能中尋找目標登錄並重新整理。 在 Azure CLI 中,執行
az login
。
網站顯示「錯誤請求(400)」
如果您收到「不正確的要求(400)」錯誤,請檢查傳入容器的PostgreSQL環境變數。 400 錯誤通常表示 Python 程式代碼無法連線到 PostgreSQL 實例。
本教學課程中使用的範例程式代碼會檢查容器環境變數是否存在 RUNNING_IN_PRODUCTION
,它可以設定為任何值(例如 1
)。
網站傳回「找不到」(404)」
- 檢查容器 概觀 頁面上 應用程式 URL 值。 如果應用程式 URL 包含「internal」這個字,則入口設定不正確。
- 檢查容器的輸入。 例如,在 Azure 入口網站中,前往容器的 入口 資源。 請確定已啟用 HTTP 入口,並選擇 [接受來自任何位置的流量]。
網站未啟動,您會收到「串流超時」提示,或沒有任何回應。
- 檢查記錄:
- 在 Azure 入口網站中,移至容器應用程式的修訂管理資源,並檢查容器 布建狀態:
- 如果狀態 配置中,請等候配置完成。
- 如果狀態為 失敗,請選取修訂並檢視主控台日誌。 選擇顯示 產生時間、Stream_s和 Log_s的欄位順序。 依最新記錄排序,並尋找
stderr
數據行中的 Pythonstdout
和 訊息。 Pythonprint
輸出stdout
訊息。
- 在 Azure CLI 中,使用 az containerapp logs show 命令。
- 在 Azure 入口網站中,移至容器應用程式的修訂管理資源,並檢查容器 布建狀態:
- 如果您使用 Django 架構,請檢查資料庫中是否有 restaurants_reviews 數據表。 如果沒有,請使用主控台來存取容器並執行
python manage.py migrate
。