一鍵部署、SSL 安全、成本優化的完整解決方案
創建並執行以下部署腳本:
#!/bin/bash
# 設定參數 - UK South 區域優化
RESOURCE_GROUP="OpenWebUI-ContainerApp-GP"
LOCATION="uksouth"
STORAGE_ACCOUNT_NAME="openwebuistorage$RANDOM"
FILE_SHARE_NAME="ai-storage-file-share"
CONTAINER_ENV_NAME="OpenWebContainerEnvironment"
CONTAINER_APP_NAME="ai-openwebcontainer"
OPENAI_API_KEY="" # 填入您的 OpenAI API Key(可選)
echo "🚀 開始部署 OpenWeb UI 到 Azure Container Apps (UK South)..."
# 1. 建立資源群組
echo "📦 建立資源群組: $RESOURCE_GROUP"
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
# 2. 建立 Storage Account
echo "💾 建立 Storage Account: $STORAGE_ACCOUNT_NAME"
az storage account create \
--resource-group $RESOURCE_GROUP \
--name $STORAGE_ACCOUNT_NAME \
--location $LOCATION \
--sku Standard_LRS \
--kind StorageV2
# 3. 取得 Storage Account Key
echo "🔑 取得 Storage Account Key"
STORAGE_KEY=$(az storage account keys list \
--resource-group $RESOURCE_GROUP \
--account-name $STORAGE_ACCOUNT_NAME \
--query "[0].value" \
--output tsv)
# 4. 建立 File Share
echo "📁 建立 File Share: $FILE_SHARE_NAME"
az storage share create \
--name $FILE_SHARE_NAME \
--account-name $STORAGE_ACCOUNT_NAME \
--account-key $STORAGE_KEY
# 5. 安裝 Container Apps 擴充功能
echo "🔧 安裝 Container Apps CLI 擴充功能"
az extension add --name containerapp --upgrade
az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights
# 6. 建立 Container Apps Environment
echo "🌐 建立 Container Apps Environment: $CONTAINER_ENV_NAME"
az containerapp env create \
--name $CONTAINER_ENV_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION
# 7. 設定 Azure Files Storage
echo "🔗 設定 Azure Files 儲存"
az containerapp env storage set \
--name $CONTAINER_ENV_NAME \
--resource-group $RESOURCE_GROUP \
--storage-name "mystorage" \
--storage-type "AzureFile" \
--azure-file-account-name $STORAGE_ACCOUNT_NAME \
--azure-file-account-key $STORAGE_KEY \
--azure-file-share-name $FILE_SHARE_NAME \
--access-mode "ReadWrite"
# 8. 部署 Container App(成本優化配置)
echo "🐳 部署 OpenWeb UI Container App: $CONTAINER_APP_NAME"
ENV_VARS=""
if [ ! -z "$OPENAI_API_KEY" ]; then
ENV_VARS="--env-vars OPENAI_API_KEY=$OPENAI_API_KEY"
fi
az containerapp create \
--name $CONTAINER_APP_NAME \
--resource-group $RESOURCE_GROUP \
--environment $CONTAINER_ENV_NAME \
--image "ghcr.io/open-webui/open-webui:main" \
--target-port 8080 \
--ingress external \
--min-replicas 0 \
--max-replicas 1 \
--cpu 2 \
--memory 4Gi \
$ENV_VARS
# 9. 應用完整 Volume Mount 配置
echo "📎 設定 Volume Mount 和持久化儲存"
cat > container-config.yaml << EOF
properties:
template:
containers:
- name: $CONTAINER_APP_NAME
image: ghcr.io/open-webui/open-webui:main
resources:
cpu: 2
memory: 4Gi
volumeMounts:
- volumeName: ai-openweb-volume
mountPath: /app/backend/data
env:
$(if [ ! -z "$OPENAI_API_KEY" ]; then echo " - name: OPENAI_API_KEY"; echo " value: \"$OPENAI_API_KEY\""; fi)
scale:
minReplicas: 0
maxReplicas: 1
volumes:
- name: ai-openweb-volume
storageType: AzureFile
storageName: mystorage
mountOptions: nobrl
EOF
az containerapp update \
--name $CONTAINER_APP_NAME \
--resource-group $RESOURCE_GROUP \
--yaml container-config.yaml
# 10. 取得應用程式 URL
echo "🌍 取得應用程式 URL"
APP_URL=$(az containerapp show \
--name $CONTAINER_APP_NAME \
--resource-group $RESOURCE_GROUP \
--query "properties.configuration.ingress.fqdn" \
--output tsv)
echo "✅ 部署完成!"
echo "📋 部署資訊:"
echo " 區域: UK South (uksouth)"
echo " Resource Group: $RESOURCE_GROUP"
echo " Storage Account: $STORAGE_ACCOUNT_NAME"
echo " Container App: $CONTAINER_APP_NAME"
echo " 應用程式 URL: https://$APP_URL"
echo " 成本優化: 自動縮放 0-1 replica"
# 清理臨時檔案
rm -f container-config.yaml
echo ""
echo "🔧 下一步:SSL 證書設定"
echo " 1. 準備 Cloudflare Origin Certificate"
echo " 2. 設定自定義域名"
echo " 3. 完成 DNS 配置"
nano deploy-openwebui.shchmod +x deploy-openwebui.sh./deploy-openwebui.sh在 Cloudflare Dashboard → SSL/TLS → Origin Server 創建證書,並合併為單一檔案:
-----BEGIN CERTIFICATE-----
[Cloudflare Origin Certificate content]
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
[Private Key content]
-----END PRIVATE KEY-----
首先取得域名驗證 ID:
az containerapp show \
--name ai-openwebcontainer \
--resource-group OpenWebUI-ContainerApp-GP \
--query "properties.customDomainVerificationId" \
--output tsv
然後在 Cloudflare 中設定:
| 類型 | 名稱 | 內容 | 代理狀態 |
|---|---|---|---|
| CNAME | ai | 您的 Container App FQDN | 🟠 Proxied |
| TXT | asuid.ai | 驗證 ID | DNS only |
az containerapp env certificate upload \
--name OpenWebContainerEnvironment \
--resource-group OpenWebUI-ContainerApp-GP \
--certificate-file openwebui-combined.pem \
--certificate-name "openwebui-cloudflare-cert"
az containerapp hostname bind \
--hostname ai.yourdomain.com \
--resource-group OpenWebUI-ContainerApp-GP \
--name ai-openwebcontainer \
--environment OpenWebContainerEnvironment \
--certificate "openwebui-cloudflare-cert" \
--validation-method CNAME
| 成本項目 | 24/7 運行 | 優化後使用 | 節省金額 | 節省比例 |
|---|---|---|---|---|
| Container Apps 運算 | $100-110 | $14.9-16.4 | $85-94 | 85% |
| Azure Files Storage | $2-4 | $0.8-1.2 | $1-3 | 60% |
| Log Analytics | $1-2 | $0.5-1.0 | $0.5-1 | 50% |
| 網路流量 | $1-3 | $0.1-0.4 | $0.9-2.6 | 87% |
| 總計 | $104-119 | $16.3-19.0 | $87-103 | 84% |
"YOUR_STORAGE_KEY" 而不是實際的金鑰值。
# 取得實際的 Storage Account Key(重要!)
STORAGE_KEY=$(az storage account keys list \
--resource-group OpenWebUI-ContainerApp-GP \
--account-name YOUR_ACTUAL_STORAGE_ACCOUNT_NAME \
--query "[0].value" \
--output tsv)
echo "Storage Key: $STORAGE_KEY"
# 檢查檔案清單
az storage file list \
--account-name YOUR_ACTUAL_STORAGE_ACCOUNT_NAME \
--share-name ai-storage-file-share \
--account-key "$STORAGE_KEY"
# 檢查使用量
az storage share show \
--name ai-storage-file-share \
--account-name YOUR_ACTUAL_STORAGE_ACCOUNT_NAME \
--account-key "$STORAGE_KEY" \
--query "properties.shareUsageBytes"
webui.db 檔案(200KB-1MB+)cache/、uploads/、vector_db/ 目錄存在# 檢查 Volume 配置
az containerapp show \
--name ai-openwebcontainer \
--resource-group OpenWebUI-ContainerApp-GP \
--query "properties.template.volumes"
# 檢查掛載點
az containerapp show \
--name ai-openwebcontainer \
--resource-group OpenWebUI-ContainerApp-GP \
--query "properties.template.containers[0].volumeMounts"
# 檢查環境儲存設定
az containerapp env storage list \
--name OpenWebContainerEnvironment \
--resource-group OpenWebUI-ContainerApp-GP
# 重新設定儲存
az containerapp env storage set \
--name OpenWebContainerEnvironment \
--resource-group OpenWebUI-ContainerApp-GP \
--storage-name "mystorage" \
--storage-type "AzureFile" \
--azure-file-account-name YOUR_ACTUAL_STORAGE_ACCOUNT \
--azure-file-account-key "實際的Storage Key" \
--azure-file-share-name ai-storage-file-share \
--access-mode "ReadWrite"
asuid.subdomain
cat > fix-volume-mount.yaml << EOF
properties:
template:
containers:
- name: ai-openwebcontainer
image: ghcr.io/open-webui/open-webui:main
resources:
cpu: 2
memory: 4Gi
volumeMounts:
- volumeName: ai-openweb-volume
mountPath: /app/backend/data
scale:
minReplicas: 0
maxReplicas: 1
volumes:
- name: ai-openweb-volume
storageType: AzureFile
storageName: mystorage
mountOptions: nobrl
EOF
az containerapp update \
--name ai-openwebcontainer \
--resource-group OpenWebUI-ContainerApp-GP \
--yaml fix-volume-mount.yaml