共用方式為


在 Azure 透過 PostgreSQL 部署 Python FastAPI Web 應用程式

在本教學課程,您會透過適用於 PostgreSQL 的 Azure Database 關聯式資料庫服務,將資料驅動的 Python Web 應用程式 (FastAPI) 部署至 Azure App Service。 Azure App Service 支援 Linux 伺服器環境的 Python。 如有需求,可改為參閱 Flask 教學課程Django 教學課程

顯示 Azure 中 PostgreSQL 資料庫的 App Service 圖解。

先決條件

  • 具有有效訂用帳戶的 Azure 帳戶。 如果您沒有 Azure 帳戶,可以建立一個免費帳戶
  • 具備 Python 與 FastAPI 開發的知識。

跳到結尾

如果你有安裝 Azure Developer CLI ,可以在空的工作目錄中執行以下指令,直接跳到教學結束:

azd auth login
azd init --template msdocs-fastapi-postgresql-sample-app
azd up

範例應用程式

為協助您遵循本教學課程,我們提供了採用 FastAPI 架構的 Python 應用程式範例。 若部署後不會在本機執行,請略過此部分。

若要在本機執行應用程式,請務必在本機安裝 Python 3.8 或更新版本PostgreSQL。 接著,複製範例存放庫的 starter-no-infra 分支,並變更為存放庫根目錄。

git clone -b starter-no-infra https://github.com/Azure-Samples/msdocs-fastapi-postgresql-sample-app
cd msdocs-fastapi-postgresql-sample-app

請以 .env.sample 檔案作為參考,建立包含以下內容的 .env 檔案。 將 DBNAME 的值設為本機 PostgreSQL 執行個體的現有資料庫名稱。 按照本機 PostgreSQL 執行個體所需,妥善設定 DBHOSTDBUSERDBPASS 的值。

DBNAME=<database name>
DBHOST=<database-hostname>
DBUSER=<db-user-name>
DBPASS=<db-password>

建立應用程式的虛擬環境:

py -m venv .venv
.venv\scripts\activate

安裝相依性:

python3 -m pip install -r src/requirements.txt

將應用程式安裝為可編輯套件:

python3 -m pip install -e src

使用下列命令執行應用程式範例:

# Run database migration
python3 src/fastapi_app/seed_data.py
# Run the app at http://127.0.0.1:8000
python3 -m uvicorn fastapi_app:app --reload --port=8000

1. 建立 App Service 與 PostgreSQL 資源

在此步驟中,您會建立 Azure 資源。 本教學課程中使用的步驟會建立一組預設保護資源,其中包含 App Service 和 Azure Database for PostgreSQL。 如為建立程序,您需要指定:

  • 網頁應用程式 的名稱 。 它是您 Web 應用程式 DNS 名稱的一部分。
  • 應用程式實際運行於世界中的 區域
  • 應用程式的執行階段堆疊。 您可以在此處選取要用於應用程式的 Python 版本。
  • 應用程式的主控方案。 這是定價層,其中包含應用程式的功能集和調整容量。
  • 應用程式的 [資源群組]。 資源群組允許您將應用程式所需的所有 Azure 資源分組 (在邏輯容器中)。

登入 Azure 入口網站,遵循下列步驟建立您的 Azure App Service 資源。

步驟 1:在 Azure 入口網站中:

  1. 在 Azure 入口網站頂端的搜尋欄輸入 網頁應用程式資料庫
  2. 選取 [Marketplace] 標題下標示為 [Web App + 資料庫] 的項目。 您也可以直接瀏覽至建立精靈

步驟 2:在 [建立 Web App + 資料庫] 頁面上,如下填寫表單。

  1. 資源群組 → 選擇 建立新建 ,並輸入 msdocs-python-postgres-tutorial
  2. 區域 → 您附近的任何 Azure 區域。
  3. 名稱msdocs-python-postgres-XYZ,其中 XYZ 是任意三個隨機字元。 此名稱在整個 Azure 中必須是唯一的。
  4. Runtime stackPython 3.14.
  5. PostgreSQL資料庫引擎 - 預設選擇 Flexible Server 作為資料庫引擎。 伺服器名稱和資料庫名稱也會預設為相應的值。
  6. 主控方案基本。 一切就緒後,您稍後即可擴大至生產環境的定價層。
  7. 選取 [檢閱 + 建立]
  8. 驗證完成時,選取 [建立]

步驟 3:部署需要數分鐘的時間才能完成。 在部署完成時,選取 [前往資源] 按鈕。 你會直接進入 App Service 應用程式,並建立以下資源:

  • 資源群組 → 所有已建立資源的容器。
  • App Service 方案 → 定義 App Service 的計算資源。 系統會建立基本層中的 Linux 方案。
  • 虛擬網路 → 與 App Service 應用程式整合,並隔離後端網路流量。
  • 適用於 PostgreSQL 的 Azure Database 彈性伺服器 → 只能從虛擬網路內部存取。 系統會為您在伺服器上建立資料庫和使用者。
  • 私人 DNS 區域 → 在虛擬網路啟用 PostgreSQL 伺服器的 DNS 解析。

步驟 4:如為 FastAPI 應用程式,您必須輸入啟動命令,App Service 才能啟動您的應用程式。 在 App Service 頁面上:

  1. 在側邊欄選單中,在 設定中選擇 設定。 你可能需要選擇 「離開預覽 」才能看到以下欄位。
  2. [組態] 頁面的 [一般設定] 索引標籤,於 [堆疊設定] 底下的 [啟動命令] 欄位輸入 src/entrypoint.sh
  3. 選取儲存。 出現提示時,選取 [繼續]。 若要深入了解 App Service 的應用程式組態和啟動,請參閱設定適用於 Azure App Service 的 Linux Python 應用程式

2. 驗證連線設定

建立精靈已為您產生連線變數做為應用程式設定。 應用程式設定是將連線秘密保留在程式碼存放庫外部的一個方法。 當你準備好將秘密移到更安全的地方時,請參考 Python 的 Quickstarter:Azure Key Vault 憑證客戶端函式庫

步驟一: 在 App Service 頁面的側邊欄選單中,選擇 環境變數

步驟 2:[環境變數] 頁面的 [應用程式設定] 索引標籤,確認 AZURE_POSTGRESQL_CONNECTIONSTRING 存在。 連接字串會以環境變數的形式注入執行環境。

3. 部署範例程式碼

在此步驟中,請使用 GitHub Actions 來設定 GitHub 部署。 這只是部署至 App Service 的許多方式之一,但也是在部署程序中持續整合的絕佳方式。 根據預設,每次對您的 GitHub 存放庫執行 git push 都會開始建置和部署動作。

步驟 1:在新的瀏覽器視窗中:

  1. 使用您的 GitHub 帳戶登入。
  2. 瀏覽至 https://github.com/Azure-Samples/msdocs-fastapi-postgresql-sample-app
  3. 請選取分叉
  4. 選取 [建立派生]

步驟 2:在 GitHub 頁面按下 . 鍵,以便在瀏覽器開啟 Visual Studio Code。

步驟 3:在瀏覽器的 Visual Studio Code,於總管開啟 src/fastapi/models.py。 查看生產環境所使用的環境變數,包括您在組態頁面看到的應用程式設定。

步驟 4:回到 [App Service] 頁面的左側功能表,選取 [部署] 底下的 [部署中心]

步驟 5:在 [部署中心] 頁面:

  1. 在 [來源] 中,選取 [GitHub]。 根據預設,系統會選取 GitHub Actions 作為組建提供者。
  2. 登入您的 GitHub 帳戶,並遵循提示來授權 Azure。
  3. 在 [組織] 中,選取您的帳戶。
  4. [存放庫] 選取 [msdocs-fastapi-postgresql-sample-app]
  5. 在 [分支] 中,選取 [main]
  6. 將預設選項保留為 [新增工作流程]
  7. [驗證類型],選取 [使用者指派身分識別]
  8. 在最上層的功能表中,選取 [儲存]。 App Service 會將工作流程檔案認可至 .github/workflows 目錄中選擇的 GitHub 存放庫。

步驟 6:在 [部署中心] 頁面:

  1. 選取 [記錄]。 部署執行已經啟動。
  2. 在部署執行的記錄項目選取 [建置/部署記錄]

步驟 7:您已前往 GitHub 存放庫,並看到 GitHub 動作正在執行。 工作流程檔案定義了兩個獨立階段:建置與部署。 等候 GitHub 執行到顯示 [完成] 狀態。 需要約 5 分鐘的時間。

有問題嗎? 查看疑難排解指南

4. 產生資料庫結構描述

在前面的章節,你新增了 src/entrypoint.sh 作為應用程式的啟動指令。 entrypoint.sh 包含下列行:python3 src/fastapi_app/seed_data.py。 此命令會移轉您的資料庫。 在範例應用程式,該命令只會確保資料庫已建立正確的資料表, 它不會將任何資料填入這些資料表。

在本節中,你手動執行此指令以供示範。 透過虛擬網路保護的 PostgreSQL 資料庫,執行命令的最簡單方式是使用 App Service 容器的 SSH 工作階段。

步驟一: 回到 App Service 頁面,側邊欄選單的 開發工具 區:

  1. 選擇 SSH
  2. 選擇 開始

步驟 2:在 SSH 終端機,執行 python3 src/fastapi_app/seed_data.py。 如果成功,App Service 會成功連線至資料庫。 只有 /home 的檔案變更會在應用程式重新啟動後繼續保留。 /home 以外的變更不會保留。

5.瀏覽至應用程式

步驟 1:在 [App Service] 頁面中:

  1. 從左側功能表中選取 [概觀]
  2. 選取應用程式的 URL。

步驟 2:新增幾家餐廳到清單中。 恭喜,您正在 Azure App Service 中執行 Web 應用程式,並安全地連線至 PostgreSQL 的適用於 PostgreSQL 的 Azure 資料庫。

6. 串流診斷記錄

範例應用程式會使用 Python 標準程式庫記錄模組來協助您診斷應用程式問題。 範例應用程式包含對記錄器的呼叫,如下列程式碼所示。

@app.get("/", response_class=HTMLResponse)
async def index(request: Request, session: Session = Depends(get_db_session)):
    logger.info("root called")
    statement = (
        select(Restaurant, func.avg(Review.rating).label("avg_rating"), func.count(Review.id).label("review_count"))
        .outerjoin(Review, Review.restaurant == Restaurant.id)
        .group_by(Restaurant.id)
    )

步驟 1:在 [App Service] 頁面中:

  1. 在側邊欄選單中,在 監控中選擇 App Service 日誌
  2. 在 [應用程式記錄] 下,選取 [檔案系統]
  3. 在最上層的功能表中,選取 [儲存]

步驟二: 從側邊欄選單中選擇 「記錄串流」。 您會看到應用程式的記錄,包括平台記錄和來自容器內的記錄。

事件可能需要幾分鐘的時間才會在診斷記錄顯示。 如需深入了解如何在 Python 應用程式設定記錄,請參閱為 Python 應用程式設定 Azure 監視器

7. 清除資源

完成後,您可以刪除資源群組,以從 Azure 訂用帳戶中刪除所有資源。

步驟 1:在 Azure 入口網站頂端的搜尋列中:

  1. 輸入資源群組名稱。
  2. 選取資源群組。

步驟 2:在資源群組頁面中,選取 [刪除資源群組]

步驟 3:

  1. 輸入您確認要刪除的資源群組名稱。
  2. 選取 [刪除]

1. 建立 Azure 資源並部署範例應用程式

在此步驟,您會建立 Azure 資源,並將範例應用程式部署至 Linux 的 App Service。 本教學課程中使用的步驟會建立一組預設保護資源,其中包含 App Service 和 Azure Database for PostgreSQL。

  1. 如果您尚未這麼做,請複製本機終端機的範例存放庫 starter-no-infra 分支。

    git clone -b starter-no-infra https://github.com/Azure-Samples/msdocs-fastapi-postgresql-sample-app
    cd msdocs-fastapi-postgresql-sample-app
    

    此複製分支就是您的起點。 其中包含簡單的資料驅動 FastAPI 應用程式。

  2. 從存放庫根目錄執行 azd init

    azd init --template msdocs-fastapi-postgresql-sample-app
    
  3. 出現提示時,請提供下列答案:

    問題 Answer
    目前的目錄不是空的。 您是否要在 '<your-directory>' 初始化專案? Y
    您要對這些檔案執行什麼動作? 維持現有的檔案不變
    輸入新的環境名稱 輸入唯一名稱。 AZD 範本會在 Azure 將此名稱當作 Web 應用程式的 DNS 名稱一部分 (<app-name>.azurewebsites.net)。 允許英數字元與連字號。
  4. 執行 azd up 命令來佈建必要的 Azure 資源並部署應用程式程式碼。 如果你還沒登入 Azure,瀏覽器會啟動並要求你登入。 指令 azd up 也會提示你選擇想要的訂閱和部署地點。

    azd up
    

    azd up 命令需要幾分鐘的時間才能完成。 該命令也會編譯並部署您的應用程式程式碼。 執行時,此命令會提供佈建和部署程序的相關資訊,包括 Azure 中部署的連結。 完成時,該命令也會顯示部署應用程式的連結。

    此 AZD 範本包含的檔案 (azure.yamlinfra 目錄) 會使用下列 Azure 資源產生預設安全的架構:

    • 資源群組 → 所有已建立資源的容器。
    • App Service 方案 → 定義 App Service 的計算資源。 系統會指定 B1 層的 Linux 方案。
    • 虛擬網路 → 與 App Service 應用程式整合,並隔離後端網路流量。
    • 適用於 PostgreSQL 的 Azure Database 彈性伺服器 → 只能從虛擬網路內部存取。 系統會為您在伺服器上建立資料庫和使用者。
    • 私人 DNS 區域 → 在虛擬網路啟用 PostgreSQL 伺服器的 DNS 解析。
    • Log Analytics 工作區 → 擔任應用程式傳送記錄的目標容器,您也可在其中查詢記錄。
  5. 指令完成後 azd up ,在輸出中記錄 訂閱 IDApp 服務資源群組 的數值。 您會在下列各節用到它。 你的輸出應該會像以下(部分)輸出類似:

    Subscription: Your subscription name (1111111-1111-1111-1111-111111111111)
    Location: East US
    
      You can view detailed progress in the Azure Portal:
      https://portal.azure.com/#view/HubsExtension/DeploymentDetailsBlade/~/overview/id/%2Fsubscriptions%2F1111111-1111-1111-1111-111111111111%2Fproviders%2FMicrosoft.Resources%2Fdeployments%2Fyourenv-1721867673
    
      (✓) Done: Resource group: yourenv-rg
      (✓) Done: Virtual Network: yourenv-e2najjk4vewf2-vnet
      (✓) Done: App Service plan: yourenv-e2najjk4vewf2-service-plan
      (✓) Done: Log Analytics workspace: yourenv-e2najjk4vewf2-workspace
      (✓) Done: Application Insights: yourenv-e2najjk4vewf2-appinsights
      (✓) Done: Portal dashboard: yourenv-e2najjk4vewf2-dashboard
      (✓) Done: App Service: yourenv-e2najjk4vewf2-app-service
      (✓) Done: Azure Database for PostgreSQL flexible server: yourenv-e2najjk4vewf2-postgres-server
      (✓) Done: Cache for Redis: yourenv-e2najjk4vewf2-redisCache
      (✓) Done: Private Endpoint: cache-privateEndpoint
    
    SUCCESS: Your application was provisioned in Azure in 32 minutes.
    You can view the resources created under the resource group yourenv-rg in Azure Portal:
    https://portal.azure.com/#@/resource/subscriptions/1111111-1111-1111-1111-111111111111/resourceGroups/yourenv-rg/overview
    
    Deploying services (azd deploy)
    
      (✓) Done: Deploying service web
      - Endpoint: https://yourenv-e2najjk4vewf2-app-service.azurewebsites.net/
    
    

2. 檢查資料庫連接字串

AZD 範本會為您產生應用程式設定的連線變數。 應用程式設定是將連線秘密保留在程式碼存放庫外部的一個方法。

  1. infra/resources.bicep 檔案找到應用程式設定,並尋找 AZURE_POSTGRESQL_CONNECTIONSTRING 的設定。

    resource appSettings 'config' = {
      name: 'appsettings'
      properties: {
          SCM_DO_BUILD_DURING_DEPLOYMENT: 'true'
          AZURE_POSTGRESQL_CONNECTIONSTRING: 'dbname=${pythonAppDatabase.name} host=${postgresServer.name}.postgres.database.azure.com port=5432 sslmode=require user=${postgresServer.properties.administratorLogin} password=${databasePassword}'
          SECRET_KEY: secretKey
          AZURE_REDIS_CONNECTIONSTRING: 'rediss://:${redisCache.listKeys().primaryKey}@${redisCache.name}.redis.cache.windows.net:6380/0'
        }
    }
    
  2. AZURE_POSTGRESQL_CONNECTIONSTRING 包含與 Azure 的 Postgres 資料庫連接的連接字串。 您必須在程式碼使用該字串以連線。 您可以在 src/fastapi/models.py 找到使用此環境變數的程式碼:

    sql_url = ""
    if os.getenv("WEBSITE_HOSTNAME"):
        logger.info("Connecting to Azure PostgreSQL Flexible server based on AZURE_POSTGRESQL_CONNECTIONSTRING...")
        env_connection_string = os.getenv("AZURE_POSTGRESQL_CONNECTIONSTRING")
        if env_connection_string is None:
            logger.info("Missing environment variable AZURE_POSTGRESQL_CONNECTIONSTRING")
        else:
            # Parse the connection string
            details = dict(item.split('=') for item in env_connection_string.split())
    
            # Properly format the URL for SQLAlchemy
            sql_url = (
                f"postgresql://{quote_plus(details['user'])}:{quote_plus(details['password'])}"
                f"@{details['host']}:{details['port']}/{details['dbname']}?sslmode={details['sslmode']}"
            )
    
    else:
        logger.info("Connecting to local PostgreSQL server based on .env file...")
        load_dotenv()
        POSTGRES_USERNAME = os.environ.get("DBUSER")
        POSTGRES_PASSWORD = os.environ.get("DBPASS")
        POSTGRES_HOST = os.environ.get("DBHOST")
        POSTGRES_DATABASE = os.environ.get("DBNAME")
        POSTGRES_PORT = os.environ.get("DBPORT", 5432)
    
        sql_url = f"postgresql://{POSTGRES_USERNAME}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DATABASE}"
    
    engine = create_engine(sql_url)
    

3. 檢查啟動命令

Azure App Service 需要啟動命令才能執行 FastAPI 應用程式。 AZD 範本會在 App Service 執行個體為您設定此命令。

  1. infra/resources.bicep 檔案尋找網站的宣告,然後尋找 appCommandLine 的設定。 這就是啟動命令的設定。

    resource web 'Microsoft.Web/sites@2024-11-01' = {
      name: '${prefix}-app-service'
      location: location
      tags: union(tags, { 'azd-service-name': 'web' })
      kind: 'app,linux'
      properties: {
        serverFarmId: appServicePlan.id
        siteConfig: {
          alwaysOn: true
          linuxFxVersion: 'PYTHON|3.11'
          ftpsState: 'Disabled'
          appCommandLine: 'src/entrypoint.sh'
          minTlsVersion: '1.2'
        }
        httpsOnly: true
      }
      identity: {
        type: 'SystemAssigned'
      }
    
  2. 啟動命令會執行 src/entrypoint.sh 檔案。請檢查該檔案的程式碼,以便了解 App Service 為了啟動應用程式而執行的命令:

    #!/bin/bash
    set -e
    python3 -m pip install --upgrade pip
    python3 -m pip install -e src
    python3 src/fastapi_app/seed_data.py
    python3 -m gunicorn fastapi_app:app -c src/gunicorn.conf.py
    

若要深入了解 App Service 的應用程式組態和啟動,請參閱設定適用於 Azure App Service 的 Linux Python 應用程式

4. 產生資料庫結構描述

您可能已在上一節注意到 entrypoint.sh 包含下列行:python3 src/fastapi_app/seed_data.py。 此命令會移轉您的資料庫。 在範例應用程式,該命令只會確保資料庫已建立正確的資料表, 它不會將任何資料填入這些資料表。

在本節,出於示範目的,您必須手動執行此命令。 透過虛擬網路保護的 PostgreSQL 資料庫,執行命令的最簡單方式是使用 App Service 容器的 SSH 工作階段。

  1. 使用您先前在 azd 輸出中注意到的 App Service 值來建構 SSH 工作階段的 URL,並在瀏覽器中瀏覽至它:

  2. 在 SSH 終端機,執行 python3 src/fastapi_app/seed_data.py。 如果成功,App Service 會成功連線至資料庫

    螢幕擷取畫面所示為要在 SSH 殼層及其輸出 (FastAPI) 執行的命令。

    附註

    只有 /home 的檔案變更會在應用程式重新啟動後繼續保留。 /home 以外的變更不會保留。

5.瀏覽至應用程式

  1. 在 azd 輸出中尋找您應用程式的 URL,並在瀏覽器前往該 URL。 在 AZD 輸出中,URL 看起來像這樣:

    Deploying services (azd deploy)
    
      (✓) Done: Deploying service web
      - Endpoint: &lt;URL>
    
  2. 將幾家餐廳新增至清單中。

    Fast API 網頁應用程式的截圖,搭配 Azure 中執行的 PostgreSQL 顯示餐廳和餐廳評論。

    恭喜,您正在 Azure App Service 中執行 Web 應用程式,並安全地連線至 PostgreSQL 的適用於 PostgreSQL 的 Azure 資料庫。

6. 串流診斷記錄

Azure App Service 會擷取記錄,協助您診斷應用程式的問題。 基於方便,AZD 範本已經啟用本機文件系統的記錄功能

範例應用程式會使用 Python 標準程式庫記錄模組來輸出記錄。 範例應用程式包含對記錄器的呼叫。

@app.get("/", response_class=HTMLResponse)
async def index(request: Request, session: Session = Depends(get_db_session)):
    logger.info("root called")
    statement = (
        select(Restaurant, func.avg(Review.rating).label("avg_rating"), func.count(Review.id).label("review_count"))
        .outerjoin(Review, Review.restaurant == Restaurant.id)
        .group_by(Restaurant.id)
    )

若要存取記錄數據流,請在 Azure 入口網站中開啟您的應用程式。 選取 [監視>記錄數據流]。

事件可能需要幾分鐘的時間才會在診斷記錄顯示。 深入了解設定適用於 Python 應用程式的 Azure 監視器 (機器翻譯) 系列中 Python 應用程式中的記錄。

7. 清除資源

若要刪除目前部署環境的所有 Azure 資源,請執行 azd down

azd down

疑難排解

以下清單描述了你在嘗試完成此教學時可能遇到的問題及解決步驟。

我無法連線至 SSH 工作階段

如果你無法連接 SSH 會話,代表應用程式本身無法啟動。 如需詳細資訊,請檢查診斷記錄。 舉例來說,如果您看到 KeyError: 'AZURE_POSTGRESQL_CONNECTIONSTRING' 這類錯誤,可能表示缺少環境變數 (您可能已移除應用程式設定)。

我在執行資料庫移轉時收到錯誤

如果您遇到與連線至資料庫的任何相關錯誤,請檢查應用程式設定 (AZURE_POSTGRESQL_CONNECTIONSTRING) 是否有變更。 若缺少該連接字串,移轉命令就無法與資料庫通訊。

常見問題集

這設定會產生多少費用?

已建立資源的定價如下:

如何使用其他工具連線到在虛擬網路後方受保護的 PostgreSQL 伺服器?

  • 若要從命令列工具進行基本存取,您可以從應用程式的 SSH 終端機執行 psql
  • 若要從桌面工具連線,您的電腦必須位於虛擬網路內。 舉例來說,該電腦可以是連線到其中一個子網路的 Azure VM,或在內部部署網路與 Azure 虛擬網路有站對站 VPN 連線的電腦。
  • 您也可以將 Azure Cloud Shell 與虛擬網路整合

本機應用程式開發如何與 GitHub Actions 搭配運作?

舉 App Service 自動產生的工作流程檔案為例,每個 git push 都會開始執行新的組建和部署。 從 GitHub 存放庫的本機複本,對 GitHub 進行所需的更新和推送。 例如:

git add .
git commit -m "<some-message>"
git push origin main

後續步驟

了解如何使用自訂網域和憑證保障您的應用程式。

了解 App Service 如何執行 Python 應用程式。