App Service (Web App) 轉向 Azure Container Apps (ACA) 完整 CLI 指令

整理了從建立 Resource Group 到佈署 ACA 的完整 CLI 指令。


第一部分:Azure CLI 指令集

請確保你的 Azure CLI 已安裝 containerapp 擴充功能:az extension add --name containerapp

1. 建立資源群組 (Resource Group)

Bash

az group create \
  --name my-aca-rg \
  --location taiwannorth

2. 建立 Log Analytics 工作區

ACA 需要一個工作區來儲存日誌。

Bash

az monitor log-analytics workspace create \
  --resource-group my-aca-rg \
  --workspace-name my-aca-logs \
  --location taiwannorth

3. 建立 Container Apps Environment

這是 ACA 的基礎設施邊界。根據你的需求,我們不設定 VNet 整合。

Bash

az containerapp env create \
  --name my-aca-env \
  --resource-group my-aca-rg \
  --logs-workspace my-aca-logs \
  --location taiwannorth

4. 佈署 Container App

假設你的映像檔在 Docker Hub 或公共倉庫(若是私有倉庫如 ACR,則需額外參數)。

Bash

az containerapp create \
  --name my-web-app \
  --resource-group my-aca-rg \
  --environment my-aca-env \
  --image mcr.microsoft.com/k8se/quickstart:latest \
  --target-port 80 \
  --ingress external \
  --query properties.configuration.ingress.fqdn

第二部分:關於「不連內網」與「其他服務整合」

你的需求是 「不需連內網 (VNet)」,這在 ACA 中被稱為 Managed Environment

1. 這是否會影響與其他 Azure 服務的溝通?

不會。 即使不加入自定義 VNet,ACA 預設就能透過 公用端點 (Public Endpoint) 與其他 Azure 服務溝通,例如:

  • Azure SQL / Cosmos DB: 透過公用存取或防火牆白名單連接。
  • Blob Storage: 透過 SDK 直接存取。
  • Static Web Apps (SWA): 這兩者經常搭配使用。

2. 與「靜態網頁 (Static Web Apps)」的整合場景

這是一個非常經典的架構:

  • 前端: 使用 Azure Static Web Apps 佈署 React/Vue/Angular。它全球佈署,速度快且成本極低。
  • 後端: 使用 Azure Container Apps 作為 API Server 或處理複雜邏輯。
  • 串接方式: 1. 你可以在 SWA 的設定中,將 ACA 的 FQDN 設定為 API 的來源。2. 利用 SWA 的 “Bring your own backend” (BYOB) 功能,將 ACA 連結到 SWA,這樣前端請求 /api 時,Azure 會自動路由到你的 ACA,且不需要處理跨網域 (CORS) 問題。

補充建議

  • 成本控制: ACA 的優勢在於可以「縮減至 0 (Scale to Zero)」,如果你的服務不是 24/7 都有流量,這比 Web App 便宜非常多。
  • 安全性: 既然不使用 VNet,建議在 ACA 內啟用 Managed Identity (受控識別) 來存取 Key Vault 或資料庫,這樣就不需要在程式碼裡寫死密碼。

你的 Web App 目前是跑什麼樣的程式語言?如果涉及私有映像檔倉庫(如 ACR),我再幫你補上相關的認證指令。


佈署 Container App, 只能用 http (port:80) 不能用 https 連?

在 Azure Container Apps (ACA) 中,關於連線協議的設計非常明確:對外(Ingress)強制使用 HTTPS,而內部(Container 之間)則可以使用 HTTP

以下是針對你疑問的詳細拆解:

1. 對外連線:強制 HTTPS

當你將 ingress 設定為 external 時,Azure 會自動為你的 Container App 提供一個預設的 FQDN(例如 my-app.taiwannorth.azurecontainerapps.io),並且:

  • 自動處理 SSL/TLS 憑證: Azure 會自動管理並為該網址簽發憑證。
  • 強制導向: 預設情況下,所有來自外部的 HTTP (Port 80) 請求都會被自動轉址 (Redirect) 到 HTTPS (Port 443)
  • 安全性: 你不需要在容器內部處理複雜的憑證設定,這些都在 ACA 的邊界(Ingress)層級處理掉了。

2. 內部通訊:可以使用 HTTP

雖然外部使用者必須透過 HTTPS 連線,但你的 容器內部(Container Port) 通常只需要監聽 HTTP 即可。

  • SSL Termination (SSL 卸載): 流量到達 ACA 環境的入口時,HTTPS 會被「卸載」。接著,ACA 的負載平衡器會透過 HTTP 將流量轉發給你的容器。
  • 指令中的 --target-port 80 這就是告訴 ACA,你的程式碼在容器內監聽的是 Port 80。

[!TIP]

結論: 使用者訪問你的網址時「一定是用 https」,但你寫程式時,只要讓 App 監聽 http port 就可以了。


3. 如果你想更動 Ingress 設定

如果你希望調整,以下是相關的指令邏輯:

需求指令參數說明
開放給所有人--ingress external提供 HTTPS 公開網址。
僅限環境內溝通--ingress internal只有同個 ACA Environment 內的服務可互連,不對外。
指定容器監聽 Port--target-port 8080如果你的 App 跑在 8080,請務必對應。
傳輸協議--transport http預設為 http,支援 http2 或 grpc。

4. 與靜態網頁 (Static Web App) 串接時的 HTTPS

既然你提到可能配合「靜態網頁」使用:

  • Static Web Apps 同樣強制 HTTPS。
  • 由於兩者都是 HTTPS,在瀏覽器端發送 API 請求時,不會遇到「混合內容 (Mixed Content)」的安全警告。

最後一個小提醒:

taiwannorth (台北) 部署時,請確認你的 CLI 版本是最新的,因為新區域的資源類型有時需要最新版的 API 支援。

你的程式碼是使用特定的框架(如 .NET, Node.js, Python)嗎?我可以幫你確認該框架預設的 Port 是否需要調整。


–target-port 參數要換成 443?

不需要。在 --target-port 參數中,你應該維持設定為你的程式(容器)真正監聽的 Port(通常是 80, 8080 或 5000),而不是 443。

這裡有一個關鍵觀念:ACA 的 Ingress 層會幫你做「SSL 卸載 (SSL Termination)」。

為什麼不填 443?

  1. 流量轉發流程:
    • 外部使用者:透過 https://... (Port 443) 訪問你的 FQDN。
    • ACA Ingress 控制器:接收 HTTPS 流量,處理 SSL 憑證,解密後將流量轉為 HTTP
    • 你的容器:接收來自 Ingress 轉發的 HTTP 流量。
  2. 容器內部配置:大多數 Docker 映像檔(例如 Nginx, Node.js, Python)在容器內預設都是跑 HTTP (Port 80/8080)。如果你強行設定 --target-port 443,ACA 會試圖把流量導向容器的 443 Port,但如果你的程式沒在該 Port 監聽或沒配置憑證,連線就會失敗。

指令情境建議

  • 如果你的程式碼監聽 80 (如 Nginx 預設):Bash--target-port 80
  • 如果你的程式碼監聽 8080 (如 Spring Boot 或許多 Node.js 框架):Bash--target-port 8080
  • 只有在一種極罕見的情況下才用 443:除非你自己把 SSL 憑證打包進 Docker Image 裡,並且讓你的程式碼直接監聽 443 Port 並處理加密(這在雲端原生架構中不建議,因為管理憑證很麻煩)。

總結

外部連線時,Azure 會強制幫你加密,所以使用者看到的絕對是 https://

驗證方法:

部署完成後,你可以試著在瀏覽器輸入 http://<你的網址>,你會發現它會自動跳轉成 https://<你的網址>。這證明了 HTTPS 是在「入口處」就處理好的,跟你的 --target-port 設定無關。

目前你的 Web App 程式碼裡面,監聽的是哪個 Port 呢?

發佈留言

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