[Cloud CICD] 後端篇 - .Net8 WebApi, Github Action, Azure App Service
前言:本篇記錄了將 .NET 8 Web API 專案部署到 Azure App Service 的完整流程,包含 GitHub Actions 自動化部署設定。重點包含 Publish Profile 設定、環境變數階層設定,以及 Database 防火牆 IP 白名單設定。
📦 技術堆疊
🗺️ 部署流程總覽
📝 詳細步驟
1推送 .NET 8 Web API 專案至 GitHub
確保你的 .NET 8 Web API 專案已建立並推送到 GitHub Repository。
project-root/ ├── Controllers/ # API Controllers ├── Models/ # 資料模型 ├── Services/ # 商業邏輯 ├── appsettings.json # 開發環境設定 ├── appsettings.Production.json # 正式環境設定 ├── Program.cs └── YourProject.csproj
git init git add . git commit -m "Initial commit: .NET 8 Web API" git remote add origin https://github.com/你的帳號/你的專案.git git push -u origin main
2在 Azure Portal 建立 App Service
- 登入 Azure Portal
- 搜尋「App Services」→ 點擊「建立」→「Web 應用程式」
- 填寫基本資訊:
- 訂用帳戶:選擇你的訂用帳戶
- 資源群組:建立新的或選擇現有的
- 名稱:輸入應用程式名稱(例如:my-dotnet8-api)
- 發佈:程式碼
- 執行階段堆疊:.NET 8 (LTS)
- 作業系統:Windows 或 Linux
- 區域:East Asia
- 定價方案:
- 開發/測試:F1(免費)或 B1(基本)
- 生產環境:S1 或以上
- 點擊「檢閱 + 建立」→「建立」
3下載 Publish Profile(關鍵步驟)
部署完成後,進入你的 App Service:
- 在左側選單找到「部署」→ 選擇「部署中心」
- 或直接在頂部工具列點擊「取得發行設定檔」按鈕
- 會下載一個
.PublishSettings檔案 - 用文字編輯器開啟這個檔案,複製整個檔案的內容
這個 Publish Profile 包含敏感資訊(帳號密碼),絕對不要直接提交到 Git Repository!我們會將它安全地儲存在 GitHub Secrets 中。
4在 GitHub 設定 Secrets
前往你的 GitHub Repository:
- 點擊「Settings」頁籤
- 在左側選單找到「Secrets and variables」→「Actions」
- 點擊「New repository secret」
- 設定如下:
- Name:
AZURE_WEBAPP_PUBLISH_PROFILE - Secret:貼上剛才複製的 Publish Profile 內容
- Name:
- 點擊「Add secret」儲存
Secret 名稱必須是 AZURE_WEBAPP_PUBLISH_PROFILE,這樣 GitHub Actions 才能正確讀取。
5建立 GitHub Actions Workflow
在專案根目錄建立 .github/workflows/azure-deploy.yml:
name: Deploy .NET 8 API to Azure
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# 1. Checkout 程式碼
- name: Checkout code
uses: actions/checkout@v3
# 2. 設定 .NET 8
- name: Setup .NET 8
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
# 3. 還原套件
- name: Restore dependencies
run: dotnet restore
# 4. 建置專案
- name: Build
run: dotnet build --configuration Release --no-restore
# 5. 發行專案
- name: Publish
run: dotnet publish --configuration Release --no-build --output ./publish
# 6. 部署到 Azure App Service
- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v2
with:
app-name: 'my-dotnet8-api' # 改成你的 App Service 名稱
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: ./publish
將 app-name: 'my-dotnet8-api' 改成你實際的 Azure App Service 名稱!
6推送程式碼,觸發部署
git add .github/workflows/azure-deploy.yml git commit -m "Add GitHub Actions workflow for Azure deployment" git push origin main
推送後,前往 GitHub Repository 的「Actions」頁籤,可以看到部署流程正在執行。
現在 API 已經成功部署到 Azure,但還需要設定環境變數和資料庫連線。
⚙️ 關鍵設定:Environment Variables
7設定 Azure App Service 環境變數
🔑 為什麼需要環境變數?
在 Azure 上,不應該使用 appsettings.json 儲存敏感資訊(如資料庫連線字串、API Key)。正確做法是使用 Azure App Service 的環境變數功能。
設定步驟:
- 進入你的 Azure App Service
- 在左側選單找到「Settings」→「Environment variables」
- 點擊「+ Add」新增應用程式設定
重要!使用雙底線(__)區隔階層
在 Azure App Service 中,環境變數使用 __(雙底線)來表示 JSON 的階層結構。
📌 範例對照表
原本的 appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=myserver.database.windows.net;Database=mydb;..."
},
"JwtSettings": {
"Key": "your-secret-key",
"Issuer": "your-issuer",
"Audience": "your-audience"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
轉換成 Azure Environment Variables:
| Name(變數名稱) | Value(值) |
|---|---|
ConnectionStrings__DefaultConnection |
Server=myserver.database.windows.net;Database=mydb;... |
JwtSettings__Key |
your-secret-key |
JwtSettings__Issuer |
your-issuer |
JwtSettings__Audience |
your-audience |
Logging__LogLevel__Default |
Information |
appsettings.json中的每一層用__連接- 例如:
Section:SubSection:Key→Section__SubSection__Key - 環境變數會覆蓋
appsettings.json中的相同設定
實際操作畫面:
在 Azure Portal 的 Environment variables 頁面中:
- 點擊「+ Add」
- Name:輸入變數名稱(使用
__區隔) - Value:輸入對應的值
- 點擊「OK」
- 完成所有設定後,點擊頁面上方的「Apply」儲存變更
修改環境變數後,App Service 會自動重新啟動,可能會有短暫的服務中斷。
🔥 關鍵設定:Database 防火牆
8設定 Azure Database 防火牆規則
❌ 常見錯誤
部署完成後,API 無法連線到 Azure SQL Database,錯誤訊息類似:
Cannot open server 'xxx' requested by the login. Client with IP address 'x.x.x.x' is not allowed to access the server.
原因:Azure SQL Database 預設啟用防火牆,只有白名單內的 IP 才能連線。
解決步驟:取得 App Service 的 Outbound IP
- 進入你的 Azure App Service
- 在左側選單找到「Settings」→「Networking」
- 找到「Outbound traffic configuration」區塊
- 記錄下「Outbound addresses」中列出的所有 IP(通常有 4-6 個)
Outbound addresses 可能看起來像這樣:
20.195.XX.XX, 20.195.XX.XX, 20.195.XX.XX, 20.195.XX.XX
將 IP 加入 Azure SQL Database 防火牆
- 前往你的 Azure SQL Database
- 在左側選單找到「Security」→「Networking」
- 在「Firewall rules」區塊,點擊「+ Add a firewall rule」
- 設定規則:
- Rule name:AppService-OutboundIP-1(自訂名稱)
- Start IP:貼上第一個 Outbound IP
- End IP:貼上第一個 Outbound IP(相同)
- 重複步驟 3-4,將所有 Outbound IP 都加入防火牆規則
- 點擊「Save」儲存變更
- Outbound IP 可能會在 App Service 重新啟動或擴展時變動
- 建議將所有列出的 IP 都加入防火牆,以避免連線問題
- 生產環境建議使用 VNet 整合或私人端點提高安全性
替代方案:允許 Azure 服務存取
如果你的 Database 和 App Service 在同一個 Azure 區域,可以啟用「允許 Azure 服務和資源存取此伺服器」:
- 在 Database 的「Networking」頁面
- 找到「Exceptions」區塊
- 勾選「Allow Azure services and resources to access this server」
- 點擊「Save」
這個選項會允許所有 Azure 服務存取你的資料庫,包含其他 Azure 客戶的資源。生產環境建議使用 IP 白名單或 VNet 整合。
9設定 CORS(跨來源資源共用)
🌐 什麼是 CORS?
當你的前端(例如 Vue3 應用程式)部署在 https://your-frontend.azurestaticapps.net,而後端 API 在 https://your-api.azurewebsites.net 時,瀏覽器會阻擋這種跨網域請求。
CORS(Cross-Origin Resource Sharing)就是用來允許這種跨網域存取的機制。
設定方式比較
在 Azure App Service 中,有兩種方式設定 CORS:
| 方式 | 優點 | 缺點 |
|---|---|---|
| 方法 1:程式碼 + 環境變數 |
• 可以在程式碼中完全控制 • 支援複雜的 CORS 策略 • 可以條件式設定 |
• 需要修改程式碼 • 需要重新部署才能生效 |
| 方法 2:Azure Portal 設定 |
• 無需修改程式碼 • 立即生效,無需重新部署 • 操作簡單直觀 |
• 功能較為基礎 • 與程式碼設定可能衝突 |
- 開發/測試環境:使用 Azure Portal 設定,方便快速調整
- 生產環境:使用程式碼 + 環境變數,更安全且可版控
方法 1:程式碼 + 環境變數設定(推薦)
步驟 1:修改 Program.cs
var builder = WebApplication.CreateBuilder(args);
// 讀取環境變數中的 CORS 設定
var allowedOrigins = builder.Configuration
.GetSection("CorsSettings:AllowedOrigins")
.Get<string[]>() ?? Array.Empty<string>();
// 設定 CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigins", policy =>
{
policy.WithOrigins(allowedOrigins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials(); // 如果需要傳送 Cookie
});
});
builder.Services.AddControllers();
// ... 其他服務設定
var app = builder.Build();
// 啟用 CORS(必須在 UseRouting 之後、UseAuthorization 之前)
app.UseCors("AllowSpecificOrigins");
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
步驟 2:在 appsettings.json 設定預設值(開發環境)
{
"CorsSettings": {
"AllowedOrigins": [
"http://localhost:5173", // Vite 開發伺服器
"http://localhost:3000" // 其他前端開發伺服器
]
}
}
步驟 3:在 Azure App Service 設定環境變數(生產環境)
- 進入 Azure App Service
- 左側選單:Settings → Environment variables
- 點擊「+ Add」新增以下設定:
| Name | Value |
|---|---|
CorsSettings__AllowedOrigins__0 |
https://your-frontend.azurestaticapps.net |
CorsSettings__AllowedOrigins__1 |
https://your-custom-domain.com |
- 陣列元素使用
__0、__1、__2表示索引 - 例如:
CorsSettings:AllowedOrigins[0]→CorsSettings__AllowedOrigins__0
方法 2:直接在 Azure Portal 設定
如果你不想在程式碼中處理 CORS,可以直接透過 Azure Portal 設定:
- 進入你的 Azure App Service
- 在左側選單找到「API」→「CORS」
- 在「Allowed Origins」欄位中,每行輸入一個網址:
https://your-frontend.azurestaticapps.net https://your-custom-domain.com http://localhost:5173
- (可選)勾選「Enable Access-Control-Allow-Credentials」如果需要傳送 Cookie
- 點擊「Save」儲存
絕對不要在生產環境使用萬用字元 *!
這會允許任何網站呼叫你的 API,造成嚴重的安全風險。
兩種方法衝突處理
如果你同時在程式碼中設定 CORS,又在 Azure Portal 設定 CORS,可能會造成衝突!
建議做法:
- 只選擇其中一種方法使用
- 如果使用程式碼設定,建議把 Azure Portal 的 CORS 設定保持空白
- 如果使用 Azure Portal 設定,記得移除程式碼中的 CORS 設定
測試 CORS 設定
方法 1:使用瀏覽器開發者工具
- 開啟前端網站
- 按 F12 開啟開發者工具
- 切換到「Console」或「Network」頁籤
- 呼叫 API
- 檢查是否出現 CORS 錯誤:
❌ 錯誤範例: Access to fetch at 'https://your-api.azurewebsites.net/api/users' from origin 'https://your-frontend.azurestaticapps.net' has been blocked by CORS policy
方法 2:使用 cURL 測試
curl -i -X OPTIONS https://your-api.azurewebsites.net/api/users \ -H "Origin: https://your-frontend.azurestaticapps.net" \ -H "Access-Control-Request-Method: GET"
如果 CORS 設定正確,回應中應該包含:
Access-Control-Allow-Origin: https://your-frontend.azurestaticapps.net Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: *
常見 CORS 錯誤排解
錯誤 1:The CORS protocol does not allow specifying a wildcard
原因:當你設定了 AllowCredentials() 時,不能使用 AllowAnyOrigin()
解決:改用 WithOrigins() 明確指定網址
錯誤 2:Response to preflight request doesn't pass access control check
原因:OPTIONS 請求(Preflight)失敗
解決:
- 確認
app.UseCors()的順序正確(在 UseRouting 之後) - 確認 CORS 策略名稱正確
錯誤 3:網址末尾的斜線問題
現象:https://example.com 和 https://example.com/ 被視為不同網址
解決:在 Azure 設定時不要在網址末尾加斜線
10從 SQL Database 取得連線字串並設定環境變數
完成資料庫建立和資料匯入後,需要將連線字串設定到 App Service,讓後端 API 能夠連接資料庫。
步驟 1:從 Azure SQL Database 複製連線字串
- 進入 Azure Portal,前往你的 SQL Database(不是 SQL Server)
- 在左側選單找到「Settings」→「Connection strings」
- 選擇「ADO.NET (SQL authentication)」頁籤
- 複製完整的連線字串,看起來像這樣:
Server=tcp:your-server-name.database.windows.net,1433;Initial Catalog=YourDatabaseName;Persist Security Info=False;User ID=your-username;Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
步驟 2:修改連線字串(替換密碼)
注意到連線字串中的 {your_password} 是一個佔位符號,需要替換成你在建立 SQL Server 時設定的實際密碼。
將 {your_password}(包含大括號)整個替換成你的密碼,不要只是刪除大括號!
Server=tcp:my-sql-server-2025.database.windows.net,1433;Initial Catalog=MyAppDB;Persist Security Info=False;User ID=sqladmin;Password=MyStr0ngP@ssw0rd!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
步驟 3:設定到 Azure App Service 環境變數
- 前往你的 Azure App Service
- 在左側選單找到「Settings」→「Environment variables」
- 在「Application settings」區塊,點擊「+ Add」
- 填寫以下資訊:
| Name(變數名稱) | Value(值) |
|---|---|
ConnectionStrings__DefaultConnection |
貼上步驟 2 修改後的完整連線字串 |
- 變數名稱使用 雙底線
__來表示階層 ConnectionStrings:DefaultConnection→ConnectionStrings__DefaultConnection- 如果你在
appsettings.json中使用不同的名稱(例如MyDbConnection),記得對應修改
- 點擊「OK」
- 點擊頁面上方的「Apply」儲存變更
- App Service 會自動重新啟動(約 10-30 秒)
步驟 4:在程式碼中使用連線字串
確保你的 .NET 專案中正確讀取連線字串:
var builder = WebApplication.CreateBuilder(args);
// 從 Configuration 讀取連線字串
var connectionString = builder.Configuration
.GetConnectionString("DefaultConnection");
// 註冊 DbContext
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
// ... 其他設定
var app = builder.Build();
app.Run();
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyAppDB;Trusted_Connection=True;"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
Azure App Service 的環境變數會自動覆蓋 appsettings.json 中的相同設定。所以:
- 本機開發:使用
appsettings.json中的本機資料庫 - Azure 部署:自動使用環境變數中的 Azure SQL Database
- 不需要修改程式碼,也不會把敏感資訊提交到 Git
步驟 5:測試連線
部署後測試資料庫連線是否正常:
- 前往你的 API 網址:
https://your-api.azurewebsites.net - 測試需要資料庫的 API 端點(例如:
/api/users) - 如果出現錯誤,查看 App Service 的 Log Stream:
- App Service → Monitoring → Log stream
- 選擇「Application logs」
常見錯誤排解
❌ 錯誤 1:Login failed for user
可能原因:
- 密碼錯誤(包含大括號沒有移除)
- 帳號名稱錯誤
解決方法:
- 重新從 Azure 複製連線字串
- 確認密碼完全正確(區分大小寫)
- 確認
{your_password}已被替換
❌ 錯誤 2:Cannot open server requested by the login
可能原因:
- App Service 的 Outbound IP 沒有加入 SQL Database 防火牆
解決方法:
- 回到第 6 步:設定後端防火牆(App Service Outbound IP)
- 確認所有 Outbound IP 都已加入防火牆規則
❌ 錯誤 3:A network-related or instance-specific error
可能原因:
- 連線字串格式錯誤
- 伺服器名稱或資料庫名稱錯誤
解決方法:
- 檢查連線字串中的
Server和Initial Catalog是否正確 - 確認沒有多餘的空格或換行
❌ 錯誤 4:The connection string is null or empty
可能原因:
- 環境變數名稱錯誤(沒有使用雙底線)
- 程式碼中讀取的名稱與環境變數不匹配
解決方法:
- 確認環境變數名稱:
ConnectionStrings__DefaultConnection - 確認程式碼中使用:
GetConnectionString("DefaultConnection")
額外建議:設定開發環境連線字串
為了方便本機測試 Azure SQL Database,可以新增 appsettings.Development.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=tcp:your-server.database.windows.net,1433;Initial Catalog=YourDB;User ID=sqladmin;Password=YourPassword;Encrypt=True;"
}
}
如果將 appsettings.Development.json 包含密碼,記得將此檔案加入 .gitignore,避免密碼洩漏!
✅ 完整測試流程
部署後驗證清單
- ✅ 前往你的 API 網址:
https://你的app名稱.azurewebsites.net - ✅ 測試 Swagger UI(如果有啟用):
/swagger - ✅ 測試 API 端點是否正常回應
- ✅ 檢查資料庫連線是否正常(嘗試讀取/寫入資料)
- ✅ 查看 Azure App Service 的 Log Stream 確認沒有錯誤
如何查看 Log
- 進入 Azure App Service
- 左側選單找到「Monitoring」→「Log stream」
- 選擇「Application logs」
- 即時查看應用程式的 Console 輸出
🐛 常見問題排解
問題 1:部署成功但網站顯示 500 錯誤
可能原因:
- 環境變數設定錯誤(檢查雙底線
__是否正確) - 缺少必要的環境變數
- 資料庫連線失敗
解決方法:查看 Log Stream 找出具體錯誤訊息
問題 2:Cannot open server requested by the login
原因:App Service 的 Outbound IP 沒有加入 Database 防火牆白名單
解決方法:按照步驟 8 設定防火牆規則
問題 3:GitHub Actions 部署失敗
檢查項目:
- 確認
AZURE_WEBAPP_PUBLISH_PROFILESecret 已正確設定 - 確認 workflow 檔案中的
app-name正確 - 檢查 Publish Profile 是否過期(重新下載並更新)
📚 重點整理
- Publish Profile:從 Azure 下載後儲存在 GitHub Secrets,變數名稱必須是
AZURE_WEBAPP_PUBLISH_PROFILE - 環境變數:使用
__(雙底線)區隔 JSON 階層,例如ConnectionStrings__DefaultConnection - 防火牆設定:必須將 App Service 的所有 Outbound IP 加入 Database 防火牆白名單
- Log 查看:使用 Log Stream 即時監控應用程式運作狀況
🔗 相關資源
希望這篇文章能幫助你順利部署 .NET 8 API 到 Azure!
如果遇到其他問題,歡迎留言討論 😊
留言
張貼留言