在 Azure Container Apps 建立隔離的 Demo MSSQL 資料庫

Demo 資料說明

本文是一篇教學用範例。Example Company、demoproject、Azure 資源名稱、帳號、網域與 tenant 都是虛構資料,不能直接拿來連線或部署。實際使用時,請替換成自己的環境設定。

先說結論

Example Company 的開發團隊想在 Azure Container Apps 裡快速展示 Backend 功能,但暫時不需要使用既有的 Azure SQL Database,也不需要讀取既有的 demoproject-dev 資料。

這種情況可以在同一個 Container Apps Environment 裡,另外部署一個暫時的 Microsoft SQL Server container,提供一個全新的 Demo database。

這個方案的重點是:

  • Demo SQL Server 是獨立的新資料庫。
  • Backend 不連既有的 demoproject-dev
  • 不匯入正式或 staging 資料。
  • 不使用既有 Azure SQL 的 Managed Identity、contained user 或 database roles。
  • Backend、MSSQL 和 Frontend 仍然要正確設定網路、secret、storage、health check 和 CI/CD。

換句話說,這不是把原本的 Azure SQL 搬進 container,而是建立一套隔離、短期、只供 Demo 使用的資料庫環境

為什麼需要這個方案?

假設目前的開發環境是:

cae-example-dev-001

這個 Environment 主要用來執行開發中的 Container App,但沒有連到既有 Azure SQL Private Endpoint 所需的完整 VNet 路徑。

如果 Backend 直接使用 Azure SQL,可能會遇到:

  • SQL network connection timeout。
  • Private Endpoint 無法連線。
  • Azure SQL firewall 拒絕來源 IP。
  • Managed Identity 可以取得 token,但 SQL database 沒有對應的 user 或 roles。

可是,這次 Demo 的需求並不是要存取既有資料,而是希望先讓團隊能夠:

  1. 啟動 Backend API。
  2. 建立一些測試資料。
  3. 展示查詢、新增、修改等基本功能。
  4. 讓 Frontend 能呼叫 Backend。

因此,可以把資料庫改成和 Backend 位於同一個 Container Apps Environment 的內部 MSSQL App,讓這次 Demo 不依賴既有 Azure SQL 的 Private Endpoint。

目標架構

Demo 環境可以設計成下面這樣:

Frontend 或測試工具
          │
          ▼
ca-example-backend-dev-001
          │ internal connection
          ▼
ca-example-mssql-demo-dev-001
          │ TCP 1433,僅限 internal ingress
          ▼
demoproject-demo

示範資源如下:

元件Demo 名稱用途
Container Apps Environmentcae-example-dev-001執行所有 Demo App
Backend Appca-example-backend-dev-001提供 API
MSSQL Appca-example-mssql-demo-dev-001提供 Demo database
Databasedemoproject-demo全新、隔離的測試資料
Resource Grouprg-demo-dev-001存放 Demo Container Apps

MSSQL 應該是獨立的 Container App,不要和 Backend 放在同一個 container。這樣可以分別更新 Backend 和資料庫,也比較容易在 Demo 結束時清理。

需要怎麼做?

第一步:建立獨立的 MSSQL Container App

使用官方 Microsoft SQL Server Linux container image,並固定版本或 digest,不要長期使用會隨時間變動的 latest tag。

MSSQL App 的基本設定應包含:

App name:    ca-example-mssql-demo-dev-001
Environment: cae-example-dev-001
Port:        TCP 1433
Ingress:     internal only
Database:    demoproject-demo

Container 需要設定:

  • ACCEPT_EULA=Y
  • MSSQL_PID=Developer
  • MSSQL_SA_PASSWORD
  • 足夠的 CPU 和 memory
  • TCP 1433 target port
  • readiness/startup health check

SQL Server container 通常至少需要 2 GiB memory;Demo 建議依實際啟動時間與資料量配置更多資源。

MSSQL_PID=Developer 只適合非正式 Demo,不能當成 production license 或正式 staging database。SA password 不可以寫在 Dockerfile、image、repository 或 workflow 明文中。

第二步:只開放內部網路

MSSQL App 只能使用 internal ingress:

Backend App ── internal DNS ──> MSSQL App:1433

不要把 SQL Server 的 TCP 1433 開成 public ingress,也不要讓測試人員直接從 Internet 連入。

Backend 和 MSSQL App 最簡單的做法是放在同一個 cae-example-dev-001。Backend 使用 MSSQL App 的 internal FQDN 連線,不要自行猜測 FQDN 格式,應從 Azure Container Apps 的 App 設定或 DNS 設定取得實際值。

第三步:建立專用 application login

Backend 不應使用 sa 登入。MSSQL container 第一次啟動後,應執行一次初始化流程:

  1. 建立 demoproject-demo database。
  2. 建立專用的 Backend application login。
  3. 只授予 application login 必要的 read/write 權限。
  4. 只有需要執行 schema migration 時,才授予有限的 DDL 權限。
  5. 確認 Backend 不會取得 SA password。

這個 Demo SQL Server 是獨立的 SQL container,Backend 通常會使用 SQL login/password,而不是既有 Azure SQL 的 Microsoft Entra Managed Identity flow。

因此,application login 的 username 和 password 必須放在 Container App secret 或 Key Vault secret reference 中,不能放在 source code 或公開設定檔。

第四步:修改 Backend 的 connection string

Backend 原本如果使用 Azure SQL Managed Identity,可能會包含這類設定:

fedauth=ActiveDirectoryManagedIdentity
useMsi=true

切換到 Demo MSSQL 後,Backend 必須改成:

  • SQL host:ca-example-mssql-demo-dev-001 的 internal FQDN。
  • Port:1433
  • Database:demoproject-demo
  • Username:專用 application login。
  • Password:由 secret reference 注入。
  • Authentication:使用 SQL login/password。

概念上的設定如下:

sqlserver://<mssql-internal-host>:1433
  ?database=demoproject-demo
  &user=<application-user>
  &password=<secret-reference>

實際格式要依 Backend 使用的 SQL driver 調整。不要把完整 connection string 寫進 GitHub Actions log、Dockerfile 或公開的 frontend configuration。

如果 Demo SQL Server 使用 self-signed certificate,請明確決定測試環境的 TLS 設定。即使是 Demo,也不要把關閉加密或無條件信任憑證當成正式環境的解法。

第五步:建立 schema 和測試資料

全新的 demoproject-demo 不會自動有任何 table,因此需要另外準備:

  • schema migration。
  • 初始化 seed data。
  • Demo 使用者和測試帳號。
  • API 所需的 reference data。
  • migration 失敗時的處理方式。

建議使用一次性的 bootstrap 或 job 初始化 database,不要讓每一個 Backend revision 在啟動時同時執行完整 migration,否則可能發生 migration race condition。

Demo data 應該是新建或去識別化資料,不要將正式資料直接複製到這個 container。

第六步:處理資料持久化

Container App 的 local filesystem 不適合當成可靠的 database storage。如果沒有持久化 volume,以下情況都可能讓資料消失:

  • Container restart。
  • Revision replacement。
  • App 被重新建立。
  • Node 或 host 發生故障。

如果 Demo 只做一次性展示,可以接受資料在環境重建後消失;如果需要保留測試結果,至少要:

  • 將 SQL Server data/log 目錄掛到持久化 storage,例如 Azure Files。
  • 驗證 SQL Server 在該 storage 上的 lock、I/O 和 recovery 行為。
  • 設定 backup,並將 backup 放到獨立的儲存位置。
  • 訂定資料保存期限。
  • 確認刪除 App 或 volume 時,不會誤刪唯一一份資料。

即使使用 Azure Files,這仍然不等同於 Azure SQL Database 的 HA、backup、patching、SLA 和資料庫服務保證,所以必須把它標示為 temporary demo database

第七步:把資料庫 bootstrap 和一般 CI/CD 分開

MSSQL App 不應該在每次 Backend push 時被刪除或重建。建議把流程分成兩部分。

一次性的 Demo bootstrap:

  • 建立或更新 ca-example-mssql-demo-dev-001
  • 設定 image、secret、storage、internal ingress 和 health check。
  • 等待 SQL Server ready。
  • 建立 demoproject-demo、application login、schema 和 seed data。

一般 Backend CI/CD:

  • 編譯 Backend。
  • Push Backend image 到 ACR。
  • 更新 ca-example-backend-dev-001
  • 保留 MSSQL App 和 volume,不要重新初始化 database。

Backend runtime 仍然需要自己的 ACR AcrPull。GitHub OIDC Service Principal 只負責 CI/CD 所需的 AcrPush 和 App deployment 權限,不需要 SQL database role。

如果 MSSQL image 直接從 MCR pull,必須確認 Environment 可以連到 MCR。如果團隊將 MSSQL image mirror 到 ACR,則 MSSQL App 的 runtime identity 也要另外授予 ACR AcrPull

第八步:處理啟動順序和健康檢查

SQL Server container 通常比 API container 更久才會 ready,因此 Backend 不能假設 SQL 在啟動第一秒就能連線。

需要加入:

  • MSSQL readiness/health check。
  • Backend 的 connection retry 和 backoff。
  • 將「SQL 尚未 ready」與「帳號密碼錯誤」分開記錄。
  • SQL container restart 後,Backend 自動恢復連線。
  • 避免在 logs 印出 password、完整 connection string 或 token。

az containerapp update 成功只代表 Azure 接受了 App 設定,不代表 Backend 一定已經能連到 MSSQL。必須等兩個 App 都 healthy 後,再測試 API。

Frontend 要調整什麼?

Frontend 不需要 SQL 權限,也不應取得 Backend 的 SQL credentials。

Frontend 需要確認:

  • 使用正確的 Frontend image。
  • 使用新的 Backend API URL。
  • Nginx 或其他 web server 沒有寫死舊的 Backend hostname。
  • 只有必要的 frontend secrets 被注入。

Frontend 只呼叫 Backend API;SQL connection 由 Backend 負責。

安全設定

這個 Demo 方案至少要符合以下原則:

  • MSSQL App 只有 internal ingress。
  • 不對 Internet 公開 TCP 1433
  • SA password 和 application password 都放在 secret。
  • Backend 使用專用 application login,不使用 SA。
  • 不把 SQL credentials 寫入 Git repository。
  • 不讓 Frontend 取得 SQL credentials。
  • 監控 container restart、CPU、memory、storage 和 backup。
  • 為 Demo 設定 owner、用途和到期日。
  • Demo 結束後移除 App、secret、volume 和 backup。

驗證清單

部署完成後,依照以下順序驗證:

  1. MSSQL App revision 是 Healthy / Running
  2. Backend 可以解析 MSSQL App 的 internal FQDN。
  3. Backend 可以建立 TCP 1433 connection。
  4. demoproject-demo database 存在。
  5. Backend application login 可以登入。
  6. schema migration 和 seed data 成功。
  7. Backend API 可以正常讀寫 Demo database。
  8. Backend 重啟後仍然可以重新連線。
  9. MSSQL container 重啟後,volume 和 database recovery 正常。
  10. Frontend 使用正確的 Backend URL。
  11. 沒有任何元件對 Internet 公開 SQL 1433

這個方案解決什麼、不解決什麼?

問題隔離 Demo MSSQL 方案
需要一個全新的短期測試 database可以解決
不想依賴既有 Azure SQL Private Endpoint可以避開這個依賴
必須使用既有 demoproject-dev 資料不適用
需要 Azure SQL Managed Identity authentication不會自動保留,通常要改成 SQL login
需要正式資料庫的 HA、backup、SLA不適用
Frontend 是否需要 SQL 權限仍然不需要

Demo 結束後

這個方案應該被明確記錄為:

temporary isolated demo database

Demo 結束時,依序完成:

  1. 匯出真正需要保留的 Demo 結果。
  2. 停止不再使用的 Backend 和 Frontend revision。
  3. 移除 SQL secrets 和 application credentials。
  4. 備份或刪除 Demo database volume。
  5. 刪除 MSSQL Container App。
  6. 清理 ACR 中不再使用的 Demo image。
  7. 確認後續部署不會誤連到 demoproject-demo

總結

cae-example-dev-001 自架 MSSQL container,可以讓 Example Company 快速得到一個不依賴既有 Azure SQL 的隔離 Demo database。這個方法適合短期展示和功能驗證,但不是把正式資料庫搬進 Container App,也不是正式 production database 的替代品。

真正需要完成的工作不只是部署一個 MSSQL image,還包括:

  • 建立獨立的 MSSQL App。
  • 只開放 internal TCP 1433
  • 建立專用 application login。
  • 將 Backend connection string 改成新的 Demo database。
  • 初始化 schema 和 seed data。
  • 決定是否需要持久化 storage 和 backup。
  • 將 database bootstrap 與一般 Backend CI/CD 分開。
  • 加入 health check、connection retry 和 logs 保護。
  • 在 Demo 結束後完整清理資源。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *