﻿# 重新認識 Azure App Service 與 App Service Plan 各種部署模式與執行方式

我每次需要部署網站到 App Service Plan on Linux 都會遇到各種問題，所以我大部分都會選擇 Windows 平台來部署網站應用程式，因為我對 IIS 非常熟悉，所以遇到問題通常都很容易可以解決。最近我又再次遇到需要部署網站到 App Service Plan on Linux 執行，沒意外的再次發生了意外，所以這次決定不要逃避他，好好的研究一下 App Service Plan on Linux 的運作方式與相關細節。這篇文章我就來分享我的研究整理。

![A wide banner image showcasing the concept of deploying websites on Microsoft Azure App Service  The image should illustrate a digital landscape with](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/691e0580c16b2c993429-66b0c83a-c38f-4cb9-9951-1af1e98f59eb.webp)

**App Service** 支援三種部署模式：

1.  Code
    
    直接將你的**原始碼**或**封裝檔**(JAR, WAR, ...)部署到 Azure App Service 執行，又稱 **Web App**。
    
    這種部署模式可以選擇 Windows 或 Linux 作業系統平台。
    
2.  Docker Container
    
    將你的 **Docker Image** 部署到 Azure App Service 執行，又稱 **Web App for Containers**。
    
    這種部署模式可以選擇 Windows 或 Linux 作業系統平台。
    
3.  Static Web App
    
    將你的**靜態網頁**部署到 Azure App Service 執行。
    
    這種部署模式屬於「無伺服器」架構，不需要 **App Service Plan** 就可以部署網頁。
    

**App Service Plan** 支援兩種作業系統平台：

1.  Windows
    
    基於 Windows 作業系統與 IIS 網頁伺服器，又稱 **App Service Plan on Windows**。
    
    不同的作業系統支援不同的 Runtime Stack，你可以透過以下指令查詢：
    
    ```bash
    az webapp list-runtimes --os windows
    ```
    
    ```
    Result
    --------------------
    dotnet:8
    dotnet:7
    dotnet:6
    ASPNET:V4.8
    ASPNET:V3.5
    NODE:18LTS
    NODE:16LTS
    java:1.8:Java SE:8
    java:11:Java SE:11
    java:17:Java SE:17
    java:1.8:TOMCAT:10.0
    java:11:TOMCAT:10.0
    java:17:TOMCAT:10.0
    java:1.8:TOMCAT:9.0
    java:11:TOMCAT:9.0
    java:17:TOMCAT:9.0
    java:1.8:TOMCAT:8.5
    java:11:TOMCAT:8.5
    java:17:TOMCAT:8.5
    ```
    
2.  Linux
    
    基於 Linux 作業系統與 Container 容器技術，又稱 **App Service Plan on Linux**。
    
    > 注意: **App Service Plan on Linux** 的 Web App 只能跑在**容器**中，而且不支援 `Shared` 價格層級。執行時不建議將檔案寫入到容器中，建議唯一採用「唯讀」的方式執行應用程式，需要寫入檔案就寫到 Azure Storage 為主。
    
    不同的作業系統支援不同的 Runtime Stack，你可以透過以下指令查詢：
    
    ```bash
    az webapp list-runtimes --os linux
    ```
    
    ```
    Result
    ------------------
    DOTNETCORE:8.0
    DOTNETCORE:7.0
    DOTNETCORE:6.0
    NODE:20-lts
    NODE:18-lts
    NODE:16-lts
    PYTHON:3.12
    PYTHON:3.11
    PYTHON:3.10
    PYTHON:3.9
    PYTHON:3.8
    PHP:8.2
    PHP:8.1
    PHP:8.0
    JAVA:17-java17
    JAVA:11-java11
    JAVA:8-jre8
    JBOSSEAP:7-java17
    JBOSSEAP:7-java11
    JBOSSEAP:7-java8
    TOMCAT:10.0-java17
    TOMCAT:10.0-java11
    TOMCAT:10.0-jre8
    TOMCAT:9.0-java17
    TOMCAT:9.0-java11
    TOMCAT:9.0-jre8
    TOMCAT:8.5-java11
    TOMCAT:8.5-jre8
    ```
    

基於上述的理解，我們在建立 App Service 的時候，總共有以下五種組合：

1.  Web App + Windows
    
    基本上就是將你的網站程式跑在 IIS 上的網站，部署網站時都需要有個 `web.config` 檔案，去定義 IIS 的行為。
    
    這種部署模式其實不用管到底選了什麼 Runtime Stack，反正就算你不選也通通都支援，原因就是你的程式並非跑在容器中，而是跑在一個 Windows VM 中，這台 VM 已經包含所有可用的 Runtime Stack 了！
    
    由於是 IIS 網頁伺服器的關係，只要你熟悉 IIS 的管理，基本上什麼程式都可以跑在 IIS 上面，包含靜態網頁也可以輕鬆部署。
    
2.  Web App + Linux
    
    所有選用 Linux 的 App Service 都一定會跑在**容器**中，而且會由 App Service 平台選用一個內建的 container image 來跑你上傳的程式。
    
    這種部署模式會需要選擇一個 Runtime Stack，例如 .NET 8 或 Java 17 等等。選擇不同的 Runtime Stack 會決定 App Service 使用哪個 container image 來執行你的程式。
    
    網站啟動時，App Service 會自動將你上傳的程式或檔案複製到容器中執行。例如：你選擇 `TOMCAT:10.0-java17` 的時候，部署到 Web App 的檔案就必須要部署到 `/home/site/wwwroot/app.war` 這裡(你可以透過 FTPS 上傳)，網站啟動時 App Service 會把 `app.war` 複製到 `/usr/local/tomcat/webapps/ROOT.war`，而之後就會透過容器中的 Tomcat 10 執行這個 WAR 檔。
    
    當你選擇了 Web App + Linux 組合，無論你選擇什麼 Runtime Stack 類型，都沒辦法單純的部署靜態網頁，他一定要跑特定 Runtime Stack 的程式。如果你已經選擇了 Linux 的 App Service Plan，又一定要部署純靜態的網頁的話，就必須要選擇 **Static Web App** 或透過 **Web App for Containers + Linux** 搭配[**自訂容器映像檔**](https://learn.microsoft.com/en-us/azure/app-service/configure-custom-container?tabs=debian&pivots=container-linux&WT.mc_id=DT-MVP-4015686)才能部署。
    
    > 只要你的網站部署在容器中，要重啟網站就不能用 Restart 按鈕來重開，一定要先 Stop 再 Start 才能真的重新啟動網站。
    
3.  Web App for Containers + Windows
    
    這種可以讓你指定自己的 Windows Container 容器映像檔(image)，然後部署到 App Service 執行。
    
    > 只要你的網站部署在容器中，要重啟網站就不能用 Restart 按鈕來重開，一定要先 Stop 再 Start 才能真的重新啟動網站。
    
4.  Web App for Containers + Linux
    
    這種可以讓你指定自己的 Linux Container 容器映像檔(image)，然後部署到 App Service 執行。
    
    > 只要你的網站部署在容器中，要重啟網站就不能用 Restart 按鈕來重開，一定要先 Stop 再 Start 才能真的重新啟動網站。
    
5.  Static Web App
    
    這種必須使用 [Static Web Apps CLI](https://azure.github.io/static-web-apps-cli/) (SWA CLI) 來上傳網頁檔案，不然就是透過 Azure Pipelines 或 GitHub Actions 的 CI/CD 自動部署，最後由 Azure 平台的 Static Web App 執行。
    
    相關用法我之前有寫過 [如何使用 Azure Static Web Apps CLI 手動部署靜態網站應用程式](/post/2022/10/22/Deploy-Website-using-Azure-Static-Web-Apps-CLI) 文章。
    

### 總結

整理完這篇文章，對於 App Service 的整體架構算是清晰許多，未來應該不太容易再卡關了！😊

### 相關連結

-   [App Service overview](https://learn.microsoft.com/en-us/azure/app-service/overview?WT.mc_id=DT-MVP-4015686)
-   [Choose an Azure compute service](https://learn.microsoft.com/en-us/azure/architecture/guide/technology-choices/compute-decision-tree?WT.mc_id=DT-MVP-4015686)
-   [What is Azure Static Web Apps?](https://learn.microsoft.com/en-us/azure/static-web-apps/overview?WT.mc_id=DT-MVP-4015686)
-   [Making it easier to bring your Linux based web apps to Azure App Service | Microsoft Azure Blog](https://azure.microsoft.com/en-us/blog/making-it-easier-to-bring-your-linux-based-web-apps-to-azure-app-service/?WT.mc_id=DT-MVP-4015686)
-   [Run a custom container in Azure](https://learn.microsoft.com/en-us/azure/app-service/quickstart-custom-container?WT.mc_id=DT-MVP-4015686&tabs=dotnet&pivots=container-linux-vscode)
