Azure App Service 搭配 GitHub Actions 部署 ASP.NET Core Web API

Azure App Service 是微軟提供的全託管式 Web 應用程式平台,讓開發者能專注於程式開發,不需要擔心基礎架構的管理。搭配 GitHub Actions,可以實現完全自動化的持續部署流程。這篇文章會介紹如何使用 Azure App Service 部署和管理 Web 應用程式,以及透過 GitHub Actions 實現 CI/CD 自動部署。

開發環境

  • Windows 11 + WSL2
  • ASP .NET Core 10.0
  • Azure CLI 2.82.2
  • Github CLI 2.76.2
  • Azure App Service

什麼是 Azure App Service?

Azure App Service 是一個完全託管的平台即服務 (PaaS),支援多種程式語言和框架:

  • .NET / .NET Core:原生支援,效能最佳化
  • Java:支援 Tomcat、JBoss 等容器
  • Node.js:完整的 npm 套件支援
  • Python:Django、Flask 等框架
  • PHP:Laravel、WordPress 等應用

主要特點:

  1. 自動縮放:根據流量自動調整資源
  2. 高可用性:內建負載平衡和容錯移轉
  3. 持續部署:整合 GitHub Actions、Azure DevOps
  4. 內建監控:Application Insights 即時監控
  5. 安全性:SSL/TLS、認證授權、防火牆

建立 App Service 的三個步驟

接下來會用到 Azure CLI / Github CLI 開始前分別使用以下指令登入

# github cli
gh auth login

# azure cli
az login

步驟 1️⃣ 建立 App Service Plan

App Service Plan 定義了運算資源的規格,類似虛擬主機的方案。

# 建立資源群組
az group create \
  --name Lab \
  --location eastasia

# 建立 App Service Plan
az appservice plan create \
  --name web-app \
  --resource-group Lab \
  --sku B1 \
  --is-linux

 

SKU 等級

SKU用途特色
F1 (Free)開發測試免費,共享資源
B1 (Basic)小型應用基本功能,固定費用
S1 (Standard)生產環境自動縮放、備份
P1V3 (Premium)高效能應用更多記憶體、效能

 

步驟 2️⃣ 建立 Web App

# 建立 ASP.NET Core 應用
az webapp create \
  --resource-group Lab \
  --plan web-app \
  --name azure-web-app-api \
  --runtime "DOTNETCORE:10.0"

 

常用 Runtime

  • "DOTNETCORE:10.0" - .NET 10
  • "NODE:20-lts" - Node.js 20 LTS
  • "PYTHON:3.12" - Python 3.12
  • "JAVA:17-java17" - Java 17

步驟 3️⃣ 部署應用程式

有三種部署方式:

方式 A:本機手動部署

# 發佈應用程式到指定目錄
dotnet publish AspNetCoreApp/AspNetCoreApp.csproj \
  --configuration Release \
  --output ./publish-local \
  --force

# 進入發佈目錄並建立 ZIP(重要:ZIP 結構要正確)
cd ./publish-local
zip -r ../publish-local.zip .
cd ..

# 部署到 Azure
az webapp deploy \
  --resource-group Lab \
  --name azure-web-app-api \
  --src-path ./publish-local.zip \
  --type zip

 

為什麼 ZIP 結構重要?

ZIP 內應該直接包含 *.dllappsettings.json 等檔案,而不是嵌套在 publish-local/ 目錄內。

方式 B:GitHub Actions 自動部署(推薦)

這是最推薦的方式,能實現持續部署 (CI/CD)。詳見下一章節 GitHub Actions 持續部署。

方式 C:Azure CLI 快速部署

# 從本機資料夾直接部署
az webapp up \
  --name azure-web-app-api \
  --resource-group Lab \
  --runtime "DOTNETCORE:10.0"

 


GitHub Actions 持續部署

GitHub Actions 讓你能自動化從代碼到部署的整個過程。每次 push 到 main 分支,都會自動編譯、測試、打包並部署到 Azure App Service。

架構流程

┌─────────────────┐
│  git push main  │
└────────┬────────┘
         │
         v
    ┌─────────────────────────────┐
    │  GitHub Actions Triggered   │
    └────────┬────────────────────┘
             │
    ┌────────┴─────────────────────────────┐
    │                                      │
    v                                      v
┌──────────────────────┐          ┌───────────────┐
│   Build Stage        │          │  Publish      │
│ - Checkout code      │          │  - ZIP files  │
│ - Setup .NET 10.0    │──────────┤  - Ready      │
│ - dotnet restore     │          │    for        │
│ - dotnet build       │          │    deploy     │
│ - dotnet publish     │          └───────┬───────┘
└──────────────────────┘                  │
                                          v
                          ┌──────────────────────────┐
                          │  Deploy to Azure         │
                          │  - Azure CLI login       │
                          │  - Upload ZIP            │
                          │  - App Service restart   │
                          └──────────────────────────┘

 

設定步驟

步驟 1️⃣ 建立 Service Principal

Service Principal 是一個特殊的 Azure 帳戶,用於自動化任務的認證。

# 建立 Service Principal 並取得憑證
az ad sp create-for-rbac \
  --name "github-actions-azure-web-app" \
  --role contributor \
  --scopes /subscriptions/$(az account show --query id -o tsv)/resourceGroups/Lab \
  --sdk-auth

 

輸出範例如下

{
  "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
  "resourceManagerEndpointUrl": "https://management.azure.com/",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
  "galleryEndpointUrl": "https://gallery.azure.com/",
  "managementEndpointUrl": "https://management.core.windows.net/"
}

 

⚠️ 安全提醒:這個 JSON 檔案包含敏感憑證,絕對不要納入版控!

 

步驟 2️⃣ 設定 GitHub Secret

GitHub Secrets 存放機敏資訊(如憑證),GitHub Actions 可以在執行時安全地存取。

方式 A:使用 GitHub Web UI

  1. 進入 GitHub 倉庫
  2. 點擊 SettingsSecrets and variablesActions
  3. 點擊 New repository secret
  4. 名稱:AZURE_CREDENTIALS
  5. 值:貼上上一步輸出的完整 JSON
  6. 點擊 Add secret

方式 B:使用 GitHub CLI

# 將憑證保存到臨時檔案
az ad sp create-for-rbac \
  --name "github-actions-azure-web-app" \
  --role contributor \
  --scopes /subscriptions/$(az account show --query id -o tsv)/resourceGroups/Lab \
  --sdk-auth > /tmp/azure-creds.json

# 設定為 GitHub Secret
gh secret set AZURE_CREDENTIALS \
  --repo yaochangyu/azure-web-app \
  < /tmp/azure-creds.json

# 安全地刪除本地憑證檔案
rm /tmp/azure-creds.json

 

步驟 3️⃣ 建立 Workflow 檔案

在專案根目錄建立 .github/workflows/deploy.yml

name: Deploy to Azure App Service

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      # 步驟 1:檢出程式碼
      - uses: actions/checkout@v4

      # 步驟 2:設置 .NET 環境
      - name: Setup .NET 10.0
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '10.0.x'

      # 步驟 3:恢復依賴
      - name: Restore dependencies
        run: dotnet restore AspNetCoreApp/AspNetCoreApp.csproj

      # 步驟 4:編譯專案
      - name: Build
        run: dotnet build AspNetCoreApp/AspNetCoreApp.csproj --configuration Release --no-restore

      # 步驟 5:發佈專案
      - name: Publish
        run: dotnet publish AspNetCoreApp/AspNetCoreApp.csproj --configuration Release --output ${{ github.workspace }}/publish --no-build

      # 步驟 6:建立 ZIP 部署包
      - name: Create deployment package
        run: |
          cd ${{ github.workspace }}/publish
          zip -r ../app-deployment.zip .
          cd ..

      # 步驟 7:使用 Azure CLI 登入
      - name: Azure CLI login
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      # 步驟 8:部署到 Azure App Service
      - name: Deploy to Azure App Service
        run: |
          az webapp deploy \
            --resource-group Lab \
            --name azure-web-app-api \
            --src-path app-deployment.zip \
            --type zip

      # 步驟 9:記錄部署狀態
      - name: Check deployment status
        run: |
          az webapp show \
            --resource-group Lab \
            --name azure-web-app-api \
            --query "state"

 

步驟 4️⃣ 觸發自動部署

推送程式碼到 main 分支時,GitHub Actions 會自動執行:

# 進行代碼修改
echo "# Updated" >> README.md

# 提交並推送
git add .
git commit -m "chore: update README"
git push origin main

 

透過沒有任何異動的 commit 發動部署

git commit --allow-empty -m "Trigger deployment"
git push

 

監控部署

取得目前正在運行的 action

gh run watch

 

實時查看部署狀態

  1. 進入 GitHub 倉庫
  2. 點擊 Actions 標籤
  3. 查看最新的工作流運行
  4. 點擊具體工作流查看詳細步驟

運行中 🟡 → 成功 🟢 → 應用已部署到 Azure

查看部署日誌

# 查看部署日誌
az webapp deployment source show --resource-group Lab --name azure-web-app-api

# 回傳結果
{
 "branch": null,
 "deploymentRollbackEnabled": false,
 "gitHubActionConfiguration": null,
 "id": "/subscriptions/63eaf14f-00fa-434d-8ae7-069e0f03b25a/resourceGroups/Lab/providers/Microsoft.Web/sites/azure-web-app-api/sourcecontrols/web",
 "isGitHubAction": false,
 "isManualIntegration": false,
 "isMercurial": false,
 "kind": null,
 "location": "Central US",
 "name": "azure-web-app-api",
 "repoUrl": null,
 "resourceGroup": "Lab",
 "type": "Microsoft.Web/sites/sourcecontrols"
}

 

查看最近的部署

# 查看最近的部署
az rest --method get \
  --uri "/subscriptions/63eaf14f-00fa-434d-8ae7-069e0f03b25a/resourceGroups/Lab/providers/Microsoft.Web/sites/azure-web-app-api/deployments?api-version=2022-03-01" \
  --query "value[0].properties.[id, status, end_time]"

# 回傳結果  
{
 "id": "/subscriptions/63eaf14f-00fa-434d-8ae7-069e0f03b25a/resourceGroups/Lab/providers/Microsoft.Web/sites/azure-web-app-api/deployments/22f8bb55-0e65-451b-821f-6efe8c4a1452",
 "location": "Central US",
 "name": "azure-web-app-api/22f8bb55-0e65-451b-821f-6efe8c4a1452",
 "properties": {
   "active": true,
   "author": "N/A",
   "author_email": "N/A",
   "build_summary": {
     "errors": [],
     "warnings": []
   },
   "complete": true,
   "deployer": "OneDeploy",
   "end_time": "2026-01-31T06:56:48.7623942Z",
   "id": "22f8bb55-0e65-451b-821f-6efe8c4a1452",
   "is_readonly": true,
   "is_temp": false,
   "last_success_end_time": "2026-01-31T06:56:48.7623942Z",
   "log_url": "https://azure-web-app-api.scm.azurewebsites.net/api/deployments/22f8bb55-0e65-451b-821f-6efe8c4a1452/log",
   "message": "OneDeploy",
   "progress": "",
   "received_time": "2026-01-31T06:56:42.4360886Z",
   "site_name": "azure-web-app-api",
   "start_time": "2026-01-31T06:56:43.8932073Z",
   "status": 4,
   "status_text": "",
   "url": "https://azure-web-app-api.scm.azurewebsites.net/api/deployments/22f8bb55-0e65-451b-821f-6efe8c4a1452"
 },
 "type": "Microsoft.Web/sites/deployments"
}

 

查看應用程式的即時日誌

# 查看應用程式的即時日誌
az webapp log tail \
  --resource-group Lab \
  --name azure-web-app-api

# 回傳結果
2026-01-31T13:57:29  Welcome, you are now connected to log-streaming service.
Starting Log Tail -n 10 of existing logs ----

/appsvctmp/volatile/logs/runtime/container.log 
2026-01-31T06:57:45.9165096Z info: Microsoft.Hosting.Lifetime[14]
2026-01-31T06:57:45.9165758Z       Now listening on: http://[::]:8080

2026-01-31T06:57:45.9269065Z info: Microsoft.Hosting.Lifetime[0]
2026-01-31T06:57:45.9269597Z       Application started. Press Ctrl+C to shut down.
2026-01-31T06:57:45.9356962Z info: Microsoft.Hosting.Lifetime[0]
2026-01-31T06:57:45.9357243Z       Hosting environment: Production
2026-01-31T06:57:45.9361160Z info: Microsoft.Hosting.Lifetime[0]
2026-01-31T06:57:45.9361353Z       Content root path: /home/site/wwwroot
2026-01-31T06:57:47.1606237Z warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
2026-01-31T06:57:47.1606935Z       Failed to determine the https port for redirect.
Ending Log Tail of existing logs ---
Starting Live Log Stream ---

 


檢視應用程式記錄

啟用應用程式記錄

# 啟用檔案系統記錄
az webapp log config \
  --resource-group Lab \
  --name azure-web-app-api \
  --application-logging filesystem \
  --level information

# 即時串流記錄
az webapp log tail \
  --resource-group Lab \
  --name azure-web-app-api

 

整合 Application Insights

Application Insights 可以監控應用程式效能、追蹤例外狀況。

# 啟用 Application Insights
az monitor app-insights component create \
  --app azure-web-app-insights \
  --location eastasia \
  --resource-group Lab

# 取得 Instrumentation Key
az monitor app-insights component show \
  --app azure-web-app-insights \
  --resource-group Lab \
  --query instrumentationKey

 

appsettings.json 加入:

{
  "ApplicationInsights": {
    "InstrumentationKey": "your-instrumentation-key"
  }
}

 


調整效能與擴展

垂直擴展 (Scale Up)

升級 App Service Plan 的等級:

# 升級到 Standard S1
az appservice plan update \
  --name web-app \
  --resource-group Lab \
  --sku S1

 

水平擴展 (Scale Out)

增加執行個體數量:

# 手動擴展到 3 個執行個體
az appservice plan update \
  --name web-app \
  --resource-group Lab \
  --number-of-workers 3

 

自動擴展規則

# 建立自動擴展設定(需要 Standard 以上)
az monitor autoscale create \
  --resource-group Lab \
  --resource web-app \
  --resource-type Microsoft.Web/serverfarms \
  --name auto-scale-plan \
  --min-count 1 \
  --max-count 5 \
  --count 2

# 新增 CPU 使用率規則
az monitor autoscale rule create \
  --resource-group Lab \
  --autoscale-name auto-scale-plan \
  --condition "Percentage CPU > 70 avg 5m" \
  --scale out 1

 


設定自訂網域與 SSL

新增自訂網域

# 新增自訂網域
az webapp config hostname add \
  --resource-group Lab \
  --webapp-name azure-web-app-api \
  --hostname www.example.com

 

在 DNS 設定中新增 CNAME 記錄:

www.example.com → azure-web-app-api.azurewebsites.net

 

啟用 SSL 憑證

# 建立免費的 App Service Managed Certificate
az webapp config ssl bind \
  --resource-group Lab \
  --name azure-web-app-api \
  --certificate-thumbprint auto \
  --ssl-type SNI

# 強制使用 HTTPS
az webapp update \
  --resource-group Lab \
  --name azure-web-app-api \
  --set httpsOnly=true

 


設定部署位置 (Deployment Slots)

部署位置讓你可以在不影響生產環境的情況下測試新版本。

# 建立 staging 位置
az webapp deployment slot create \
  --resource-group Lab \
  --name azure-web-app-api \
  --slot staging

# 部署到 staging
az webapp deploy \
  --resource-group Lab \
  --name azure-web-app-api \
  --slot staging \
  --src-path app.zip \
  --type zip

# 驗證無誤後,交換到生產環境
az webapp deployment slot swap \
  --resource-group Lab \
  --name azure-web-app-api \
  --slot staging \
  --target-slot production

 

優點

  • 零停機時間部署
  • 快速回滾機制
  • A/B 測試流量分流

監控與診斷

健康檢查

Program.cs 新增健康檢查端點:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/health");
app.Run();

 

在 Azure 設定健康檢查:

az webapp config set \
  --resource-group Lab \
  --name azure-web-app-api \
  --health-check-path "/health"

 

效能監控

使用 Application Insights 儀表板:

  1. 開啟 Azure Portal
  2. 前往 Application Insights
  3. 檢視效能、失敗請求、相依性

或使用 Azure Monitor Metrics:

# 檢視 CPU 使用率
az monitor metrics list \
  --resource /subscriptions/{subscription-id}/resourceGroups/Lab/providers/Microsoft.Web/sites/azure-web-app-api \
  --metric "CpuPercentage" \
  --start-time 2026-01-31T00:00:00Z \
  --end-time 2026-01-31T23:59:59Z

 


安全性最佳實踐

1. 使用 Managed Identity

避免在程式碼中硬編碼憑證:

# 啟用系統指派的受控識別
az webapp identity assign \
  --resource-group Lab \
  --name azure-web-app-api

 

2. 設定 IP 限制

# 只允許特定 IP 存取
az webapp config access-restriction add \
  --resource-group Lab \
  --name azure-web-app-api \
  --rule-name AllowOfficeIP \
  --action Allow \
  --ip-address 203.0.113.0/24 \
  --priority 100

 

3. 啟用診斷記錄

az webapp log config \
  --resource-group Lab \
  --name azure-web-app-api \
  --web-server-logging filesystem \
  --detailed-error-messages true \
  --failed-request-tracing true

 

4. 定期更新 Runtime

保持 .NET、Node.js 等 runtime 在最新的安全版本。


心得

Azure App Service 搭配 GitHub Actions,提供了完整的 PaaS 解決方案和自動化部署流程,佈署的過程輕鬆、簡單。

實作的過程中搭配 Github MCP + Azure MCP,更是大幅縮短時間。


範例位置

本文完整範例程式碼與配置:
https://github.com/yaochangyu/azure-web-app


參考資料

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo