在雲端原生 (Cloud Native) 的世界裡,無伺服器 (Serverless) 架構已經不是什麼新鮮事。今天,我們就來聊聊微軟 Azure 上的無伺服器解決方案 — Azure Function App,並實際走一遍如何用 C# 開發,最後再透過 GitHub Actions 帥氣地自動部署上去。

開發環境
- Windows 11
- WSL2 (Ubuntu 24.04.1).
- NET 8.0 SDK
- Azure Functions Core Tools v4
- Azure CLI
- VSCode
先聊聊 Azure Function App
簡單來說,Azure Function App 是一種讓你專注寫程式碼,而不用煩惱底層伺服器管理的服務。它是一個事件驅動的平台,可以因為一個 HTTP 請求、一個新的儲存體檔案、或是一個排程時間到來而觸發你的程式碼。
為什麼要用它?
- 成本效益:大部分方案都是「用多少、付多少」,沒執行就幾乎不花錢。
- 自動擴展:流量高峰來臨時,Azure 會自動幫你增加運算資源,你不用半夜起床開機器。
- 高度整合:跟 Azure 生態系的其他服務(例如儲存體、資料庫、事件中樞)整合得非常好。
怎麼選方案?挑選適合的託管計畫 (Hosting Plan)
選對方案,可以幫你省下不少錢,同時確保應用程式效能。Azure 提供了多種方案,我們來看看最常見的幾種。
| 方案 | 冷啟動 | 最長執行時間 | 擴展速度 | VNet 整合 | 適合場景 |
|---|---|---|---|---|---|
| Consumption | ✅ 有 | 10 分鐘 | 慢 | ❌ | 低頻率、成本優先、開發測試 |
| Flex Consumption | 🟡 較少 | 無限制* | 快 | ✅ | 高併發、需要快速擴展的應用 |
| Premium | ❌ 無 | 無限制* | 最快 | ✅ | 關鍵生產環境、要求穩定效能 |
| Dedicated | ❌ 無 | 無限制* | 手動 | ✅ | 已有閒置 App Service Plan 的情境 |
⚠️ 重要通知 微軟宣布,Linux Consumption Plan 將在 2028 年 9 月 30 日淘汰,建議大家未來新專案可以優先考慮 Flex Consumption Plan。
*備註:所有方案的 HTTP 觸發器都有 230 秒 的回應限制,這是 Azure Load Balancer 的限制。如果你的背景任務需要跑更久,建議研究一下 Durable Functions 的非同步模式。
對於大部分開發和測試情境,免費額度很夠用的 Consumption Plan 是個好起點。
用 C# 建立第一個 Function App
光說不練太空泛,我們直接來看一個用 .NET 8 建立的 C# 專案。
專案結構速覽
這是一個典型的 Azure Functions (.NET Isolated Worker) 專案結構:
AzureWebApp.Functions/
├── Functions/
│ ├── HttpTriggerFunction.cs # 一般的 HTTP Trigger 範例
│ └── VersionFunction.cs # 我們今天的重點:版本資訊 API
├── Models/
│ └── VersionInfo.cs # 版本資訊的資料模型
├── Program.cs # 應用程式進入點,用來註冊服務
├── host.json # Functions 執行環境的設定檔
└── AzureWebApp.Functions.csproj # 專案檔,藏了一些小技巧
實作一個「版本資訊」API
一個常見的需求是,我想知道現在線上跑的是哪個版本。我們來做一個 /api/version 端點,它會回傳目前的 Git Commit Hash、建置時間和執行環境。
VersionFunction.cs
public class VersionFunction
{
[Function("version")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "version")] HttpRequest req)
{
var assembly = Assembly.GetExecutingAssembly();
var info = new VersionInfo(assembly);
return new OkObjectResult(info);
}
}
程式碼很簡單,就是 new 一個 VersionInfo 物件然後回傳。那麼 VersionInfo 怎麼拿到 Git Commit Hash 的?
關鍵技巧:在建置時嵌入 Git 資訊
在 AzureWebApp.Functions.csproj!我們在裡面加了一個 Target,讓它在每次建置 (Build) 的時候,自動去執行 git 指令,並把結果寫入組件 (Assembly) 的 Metadata。
<PropertyGroup>
<!-- ... -->
<!-- 將 Git Commit Hash 設定為 SourceRevisionId -->
<SourceRevisionId>$(GitCommitHash)</SourceRevisionId>
<!-- 將版本資訊組合後,嵌入 AssemblyInformationalVersion -->
<InformationalVersion>$(GitCommitHash)-$(BuildTime)</InformationalVersion>
</PropertyGroup>
<!-- 在建置前自動執行,取得 Git commit hash -->
<Target Name="SetBuildInfo" BeforeTargets="GetAssemblyVersion">
<!-- 執行 git 指令,並將輸出存到 MSBuild 屬性 -->
<Exec Command="git rev-parse --short HEAD" ConsoleToMSBuild="true" IgnoreExitCode="true">
<Output TaskParameter="ConsoleOutput" PropertyName="GitCommitHash" />
</Exec>
<PropertyGroup>
<!-- 如果抓不到 Git hash (例如在 CI 環境),就給個預設值 -->
<GitCommitHash Condition="'$(GitCommitHash)' == ''">unknown</GitCommitHash>
<!-- 記錄建置時間 (UTC) -->
<BuildTime>$([System.DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"))</BuildTime>
</PropertyGroup>
</Target>
有了這個設定,程式碼裡就可以輕鬆透過 Reflection 讀到這些資訊。這招是不是很實用?
在本地端跑起來
安裝相依工具:你需要 .NET 8 SDK 和 Azure Functions Core Tools。
# 安裝 Azure Functions Core Tools curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -rs)-prod $(lsb_release -rs) main" > /etc/apt/sources.list.d/dotnetdev.list' sudo apt-get update sudo apt-get install azure-functions-core-tools-這裡使用 isolated worker model

# 安裝 .NET 8 SDK wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh chmod +x ./dotnet-install.sh ./dotnet-install.sh --channel 8.0還原、建置、啟動:
# 進入專案目錄 cd AzureWebApp.Functions # 還原 NuGet 套件 dotnet restore # 建置專案 dotnet build # 啟動本地 Functions 主機 func start測試 API: 打開瀏覽器或用 curl 測試 http://localhost:7071/api/version,你應該會看到類似下面的 JSON 結果:
{ "Version": "70b6a61", "BuildTime": "2026-02-01T14:30:00Z", "Environment": "Development" }
把 Function App 部署上 Azure
寫好了,總得部署上去。這裡介紹兩種方法:適合快速測試的「本地手動部署」,以及強烈推薦的「GitHub Actions 自動化部署」。
方法一:從自己電腦部署 (Local Deploy)
有時候只是想快速驗證一下功能,可以用 func 指令直接從本機部署。為了讓過程更順暢,專案裡提供了一個 local-deploy-azure.sh 腳本。
#!/bin/bash
# 配置變數
FUNCTION_APP_NAME="func-yao-lab-938612"
PROJECT_DIR="AzureWebApp.Functions"
# ... (省略檢查與建置步驟) ...
# 部署到 Azure Function App
echo "部署到 Azure Function App: ${FUNCTION_APP_NAME}..."
cd "$PROJECT_DIR"
func azure functionapp publish "$FUNCTION_APP_NAME"
這個腳本幫你把建置、發布的指令都包好了,只要確定你已經用 az login 登入 Azure,就可以直接執行它。
# 賦予執行權限
chmod +x ./local-deploy-azure.sh
# 執行部署
./local-deploy-azure.sh
部署成功後,腳本還會貼心地幫你抓 Function Key,讓你直接用 curl 測試。
方法二:用 GitHub Actions 玩 CI/CD (推薦)
這才是現代化的開發流程!我們希望每次把程式碼 push 到 main 分支時,就自動觸發建置和部署。
專案裡的 .github/workflows/deploy-azure-function.yml 已經幫我們定義好了整個流程。
設定步驟
建立 Service Principal (服務主體)
我們不希望把有高權限的 Publish Profile 放在外面,所以改用權限可控的 Service Principal。專案裡也提供了一個 setup-service-principal.sh 腳本,它會幫你:
- 檢查 az 和 gh (GitHub CLI) 是否安裝登入。
- 在 Azure AD 建立一個 Service Principal。
- 授權它只能存取指定的資源群組 (Resource Group)。
- 最重要的,把產生的憑證 (Credentials) 直接存進 GitHub Secrets,完全不落地。
# 執行腳本,跟著指示操作 ./setup-service-principal.sh執行成功後,你的 Github Repo 專案 Secrets 裡就會多一個 AZURE_CREDENTIALS。
檢查 Workflow 檔案
打開 .github/workflows/deploy-azure-function.yml,確認環境變數 AZURE_FUNCTIONAPP_NAME 是你自己的 Function App 名稱。
env: AZURE_FUNCTIONAPP_NAME: 'func-yao-lab-938612' AZURE_FUNCTIONAPP_PACKAGE_PATH: 'AzureWebApp.Functions' DOTNET_VERSION: '8.0.x'觸發部署
現在,只要 push 任何 commit 到 main 分支,部署就會自動開始。
# 做一些修改 git add . git commit -m "feat: add new feature" git push origin main你也可以到 GitHub 專案的 Actions 頁面,手動觸發這個 Workflow。或者是 commit 空白的內容 empty-commit.sh
#!/bin/bash # 建立空 commit 以觸發 GitHub Actions 部署 git commit --allow-empty -m "chore: trigger deployment - $(date '+%Y-%m-%d %H:%M:%S')"
Workflow 做了什麼事?
整個自動化流程大致如下:
1. Checkout code (拉取程式碼)
↓
2. Setup .NET 8.0 (設定 .NET 環境)
↓
3. Restore, Build, Publish (還原、建置、發布專案)
↓
4. Login to Azure (使用剛剛的 Secret 登入 Azure)
↓
5. Deploy to Azure (部署到 Function App)
↓
6. Health Check (呼叫 /api/version 確認部署成功)
↓
7. ✅ 部署完成
部署完成後,workflow 會自動打 /api/version 確認服務是否正常,如果回傳的 JSON 裡 Environment 變成 Production,就代表成功啦!
總結
今天我們從 Azure Function App 的基本介紹、方案選擇,一路到用 C# 實作出一個包含 Git 版本資訊的 API。最後,我們還介紹了兩種部署方式,特別是透過 GitHub Actions 建立了一套完整的 CI/CD 流程。
把繁瑣的部署工作自動化,不僅能減少人為失誤,也能讓我們更專注在核心的商業邏輯開發上。希望這篇文章對你有幫助!
專案位置
yaochangyu/azure-web-app-func-demo
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET