在 Windows 建立第一個 Service Fabric 容器應用程式

在 Service Fabric 叢集上的 Windows 容器中執行現有的應用程式,不需要變更您的應用程式。 本文會逐步引導您建立包含 Python Flask Web 應用程式的 Docker 映像,並將它部署到 Azure Service Fabric 叢集。 您也將透過 Azure Container Registry 共用容器化應用程式。 本文假設您具備 Docker 的基本知識。 您可以閱讀 Docker 概觀,以了解 Docker。

注意

本文適用於 Windows 開發環境。 Service Fabric 叢集執行階段與 Docker 執行階段必須在相同的作業系統上執行。 您無法在 Linux 叢集上執行 Windows 容器。

注意

建議您使用 Azure Az PowerShell 模組來與 Azure 互動。 請參閱安裝 Azure PowerShell 以開始使用。 若要了解如何移轉至 Az PowerShell 模組,請參閱將 Azure PowerShell 從 AzureRM 移轉至 Az

必要條件

  • 執行下列項目的開發電腦︰

    • Visual Studio 2015 或 Visual Studio 2019。
    • Service Fabric SDK 和工具
    • Docker for Windows。 取得 Docker CE for Windows (穩定)。 安裝並啟動 Docker 之後,以滑鼠右鍵按一下系統匣圖示,然後選取 [切換至 Windows 容器]。 這是執行以 Windows 為基礎的 Docker 映像時的必要步驟。
  • 有三個或更多節點在具有容器的 Windows Server 上執行的 Windows 叢集。

    在本文中,在您的叢集節點上執行且具有容器的 Windows Server 版本 (組建) 必須符合您開發電腦上的 Windows Server 版本。 這是因為您會在開發電腦上建立 Docker 映像,而且容器 OS 版本與其部署所在主機 OS 版本之間有相容性條件約束。 如需詳細資訊,請參閱 Windows Server 容器作業系統和主機作業系統的相容性

    若要判斷具有您叢集所需容器的 Windows Server 版本,請在開發電腦上從 Windows 命令提示字元執行 ver 命令。 建立叢集之前,請參閱Windows Server 容器作業系統和主機作業系統相容性

  • Azure Container Registry 中的登錄 - 在 Azure 訂用帳戶中建立容器登錄

注意

系統支援將容器部署到在 Windows 10 上執行的 Service Fabric 叢集。 如需如何設定 Windows 10 以執行 Windows 容器的資訊,請參閱本文

注意

Service Fabric 6.2 版和更新版本支援將容器部署到在 Windows Server 1709 版上執行的叢集。

定義 Docker 容器

根據位於 Docker 中樞的 Python 映像建立映像。

在 Dockerfile 中指定您的 Docker 容器。 Dockerfile 包含下列相關指示:設定您容器內的環境、載入您要執行的應用程式,以及對應連接埠。 Dockerfile 是建立映像之 docker build 命令的輸入。

建立空的目錄並建立 Dockerfile 檔案 (沒有副檔名)。 將下列內容新增至 Dockerfile 並儲存變更:

# Use an official Python runtime as a base image
FROM python:2.7-windowsservercore

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

如需詳細資訊,請參閱 Dockerfile 參考

建立基本 Web 應用程式

建立 Flask Web 應用程式,其會在連接埠 80 上接聽並傳回 Hello World!。 在相同的目錄中,建立 requirements.txt 檔案。 新增下列內容並儲存變更:

Flask

此外,建立 app.py 檔案並新增下列程式碼片段:

from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello():

    return 'Hello World!'


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

登入 Docker 並建立映像

接下來我們會建立可執行 Web 應用程式的映像。 從 Docker 提取公用映像 (如 Dockerfile) 中所示 python:2.7-windowsservercore,最佳做法是使用您的 Docker Hub 帳戶進行驗證,而不是發出匿名提取要求。

注意

提出頻繁的匿名提取要求時,您可能會看到類似 ERROR: toomanyrequests: Too Many Requests.You have reached your pull rate limit. 的 Docker 錯誤,請驗證至 Docker Hub 以避免這些錯誤。 如需詳細資訊,請參閱 使用 Azure Container Registry 管理公用內容

開啟 PowerShell 視窗,然後瀏覽至包含 Dockerfile 的目錄。 然後,執行下列命令:

docker login
docker build -t helloworldapp .

此命令會使用 Dockerfile 中的指示建立新映像,將此映像命名 (-t 標記) 為 helloworldapp。 若要建置容器映像,會先從作為應用程式新增目的地的 Docker Hub 下載基礎映像。

建置命令完成後,執行 docker images 命令以查看新映像的資訊︰

$ docker images

REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
helloworldapp                 latest              8ce25f5d6a79        2 minutes ago       10.4 GB

在本機執行應用程式

先確認您的映像在本機,再將它推送至容器登錄。

執行應用程式:

docker run -d --name my-web-site helloworldapp

name - 提供執行中容器的名稱 (而不是容器識別碼)。

容器啟動之後,要找到其 IP 位址,才能從瀏覽器連線到您正在執行的容器:

docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" my-web-site

如果該命令未傳回任何項目,請執行下列命令,以及檢查 IP 位址 的 NetworkSettings>Networks 元素:

docker inspect my-web-site

連線到執行中的容器。 開啟 Web 瀏覽器並指向傳回的 IP 位址,例如 "http://172.31.194.61""。 您應該會在瀏覽器中看到 "Hello World!" 標題顯示。

若要停止您的容器,請執行︰

docker stop my-web-site

從您的開發電腦刪除容器:

docker rm my-web-site

將映像推送至容器登錄

確認容器在開發電腦上執行後,將映像發送到 Azure Container Registry 中您的登錄。

執行 docker login以使用您的登錄 登入您的容器登錄。

下列範例會傳遞 Microsoft Entra 服務主體的識別碼和密碼。 例如,您可能基於自動化案例已指派服務主體到您的登錄庫。 或者,您可以使用登錄使用者名稱和密碼進行登入。

docker login myregistry.azurecr.io -u xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -p myPassword

下列命令會建立映像的標籤或別名,包含登錄的完整路徑。 這個範例會指定 samples 命名空間中的映像,以避免登錄根目錄雜亂。

docker tag helloworldapp myregistry.azurecr.io/samples/helloworldapp

將映像推送至容器登錄:

docker push myregistry.azurecr.io/samples/helloworldapp

在 Visual Studio 中建立容器化服務

Service Fabric SDK 和工具會提供一個服務範本,協助您建立容器化應用程式。

  1. 啟動 Visual Studio。 選取 [檔案]> [新增]> [專案]
  2. 選取 [Service Fabric 應用程式],將它命名為 "MyFirstContainer",然後按一下 [確定]
  3. 從 [服務範本] 的清單中選取 [容器]
  4. 在 [映像名稱] 中輸入 "myregistry.azurecr.io/samples/helloworldapp",也就是您推送至容器存放庫的映像。
  5. 指定服務的名稱,然後按一下 [確定]

設定通訊

容器化服務需要端點進行通訊。 將 Endpoint 元素以及通訊協定、連接埠和類型新增至 ServiceManifest.xml 檔案。 在此範例中,會使用固定的連接埠 8081。 若未指定連接埠,則會從應用程式連接埠範圍中隨機選擇連接埠。

<Resources>
  <Endpoints>
    <Endpoint Name="Guest1TypeEndpoint" UriScheme="http" Port="8081" Protocol="http"/>
  </Endpoints>
</Resources>

注意

透過適用的屬性值來宣告其他 EndPoint 元素,即可為服務新增其他 EndPoint。 每個連接埠只能宣告一個通訊協定值。

透過定義端點,Service Fabric 會將端點發佈至名稱服務。 在叢集中執行的其他服務可以解析容器。 您也可以使用反向 Proxy來執行容器對容器通訊。 將 HTTP 接聽連接埠和您想要與之通訊的服務名稱提供給反向 Proxy,並將這些都設為環境變數,便可進行通訊。

服務會接聽特定連接埠 (在此範例中為 8081)。 當應用程式部署至 Azure 中的叢集時,叢集和應用程式都會在 Azure 負載平衡器後方執行。 Azure 負載平衡器必須開啟應用程式連接埠,以便輸入的流量可以通過其傳到服務。 您可以使用 PowerShell 指令碼Azure 入口網站,在 Azure 負載平衡器中開啟這個連接埠。

設定環境變數

可以為服務資訊清單中的每個程式碼套件指定環境變數。 所有服務都有這項功能,無論是部署為容器或處理程序或來賓可執行檔。 您可以覆寫應用程式資訊清單中環境變數的值,或在部署期間將它們指定為應用程式參數。

下列服務資訊清單 XML 程式碼片段示範如何指定程式碼封裝的環境變數:

<CodePackage Name="Code" Version="1.0.0">
  ...
  <EnvironmentVariables>
    <EnvironmentVariable Name="HttpGatewayPort" Value=""/>    
  </EnvironmentVariables>
</CodePackage>

在應用程式資訊清單中可以覆寫這些環境變數︰

<ServiceManifestImport>
  <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
  <EnvironmentOverrides CodePackageRef="FrontendService.Code">
    <EnvironmentVariable Name="HttpGatewayPort" Value="19080"/>
  </EnvironmentOverrides>
  ...
</ServiceManifestImport>

設定容器連接埠對主機連接埠對應,以及容器對容器探索

設定用來與容器通訊的主機連接埠。 連接埠繫結會將服務在容器內接聽的連接埠,對應至主機上的連接埠。 在 ApplicationManifest.xml 檔案的 ContainerHostPolicies 元素中,新增 PortBinding 元素。 在本文中,ContainerPort 為 80 (如 Dockerfile 所指定,容器會公開連接埠 80),而 EndpointRef 為 "Guest1TypeEndpoint" (先前在服務資訊清單中定義的端點)。 通訊埠 8081 上服務的連入要求會對應到容器上的連接埠 80。

<ServiceManifestImport>
    ...
    <Policies>
        <ContainerHostPolicies CodePackageRef="Code">
            <PortBinding ContainerPort="80" EndpointRef="Guest1TypeEndpoint"/>
        </ContainerHostPolicies>
    </Policies>
    ...
</ServiceManifestImport>

注意

透過適用的屬性值來宣告其他 PortBinding 元素,即可為服務新增其他 PortBinding。

設定容器存放庫驗證

請參閱容器存放庫驗證,以了解如何為容器映射下載設定不同類型的驗證。

設定隔離模式

Windows 支援兩種容器隔離模式:分別為處理序和 Hyper-V。 在處理序隔離模式中,在相同主機電腦上執行的所有容器都與主機共用核心。 在 Hyper-V 隔離模式中,會在每個 Hyper-V 容器與容器主機之間隔離核心。 隔離模式是在應用程式資訊清單檔中指定的 ContainerHostPolicies 元素。 可以指定的隔離模式有 processhypervdefault。 預設值為 Windows Server 主機上的程序隔離模式。 在 Windows 10 主機上,僅支援 Hyper-V 隔離模式,因此不論其隔離模式設定為何,容器都會以 Hyper-V 隔離模式執行。 下列程式碼片段顯示如何在應用程式資訊清單檔中指定隔離模式。

<ContainerHostPolicies CodePackageRef="Code" Isolation="hyperv">

注意

可在 Ev3 和具有巢狀虛擬化支援的 Dv3 Azure SKU 上使用 hyperv 隔離模式。

設定資源控管

資源控管可限制容器在主機上可使用的資源。 應用程式資訊清單中指定的 ResourceGovernancePolicy 元素是用於宣告服務程式碼封裝的資源限制。 下列資源可設定資源限制:記憶體、MemorySwap、CpuShares (CPU relative weight)、MemoryReservationInMB、BlkioWeight (BlockIO 相對權數)。 在此範例中,service package Guest1Pkg 會在其所在的叢集節點上獲得一個核心。 記憶體限制是絕對的,因此程式碼封裝會限制為 1024MB 的記憶體 (並具有同樣的彈性保證保留)。 程式碼套件 (容器或處理序) 無法配置超過此限制的記憶體,如果嘗試這麼做,將會導致發生記憶體不足的例外狀況。 若要讓資源限制強制能夠運作,應該為服務套件內的所有程式碼套件都指定記憶體限制。

<ServiceManifestImport>
  <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
  <Policies>
    <ServicePackageResourceGovernancePolicy CpuCores="1"/>
    <ResourceGovernancePolicy CodePackageRef="Code" MemoryInMB="1024"  />
  </Policies>
</ServiceManifestImport>

設定 Docker HEALTHCHECK

從 6.1 版開始,Service Fabric 會自動將 Docker HEALTHCHECK 事件整合至其系統健康情況報告。 這表示,如果您的容器已啟用 HEALTHCHECK,每當 Docker 報告容器的健康情況狀態發生變更時,Service Fabric 就會報告健康情況。 如果 health_status 為「狀況良好」,則 Service Fabric Explorer 中的健康情況報告會顯示 OK (正常),如果 health_status 為「狀況不良」,則顯示 WARNING (警告)

從 6.4 的最新重新整理版本開始,您可以選擇是否要將 d\Docker HEALTHCHECK 評估報告為錯誤。 如果啟用此選項,當health_status狀況良好時,即會出現[確定健康情況] 報告,當health_status狀況不良時,將會出現錯誤

HEALTHCHECK 指令會指向針對監視容器健康情況而執行的實際檢查,該指令必須存在產生容器映像時使用的 Dockerfile 中。

Screenshot shows details of the Deployed Service Package NodeServicePackage.

HealthCheckUnhealthyApp

HealthCheckUnhealthyDsp

您可以將 HealthConfig 選項指定為 ApplicationManifest 中 ContainerHostPolicies 的一部份,為每個容器設定 HEALTHCHECK 行為。

<ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="ContainerServicePkg" ServiceManifestVersion="2.0.0" />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <HealthConfig IncludeDockerHealthStatusInSystemHealthReport="true"
		      RestartContainerOnUnhealthyDockerHealthStatus="false" 
		      TreatContainerUnhealthyStatusAsError="false" />
      </ContainerHostPolicies>
    </Policies>
</ServiceManifestImport>

依預設, IncludeDockerHealthStatusInSystemHealthReport 設為 trueRestartContainerOnUnhealthyDockerHealthStatus 設定為 false,而 TreatContainerUnhealthyStatusAsError 設定為 false

如果 RestartContainerOnUnhealthyDockerHealthStatus 設為 true,則報告中重複出現狀況不良的容器就會重新啟動 (可能在其他節點上重新啟動)。

如果TreatContainerUnhealthyStatusAsError設定為true,當容器的health_status狀況不良時,將會出現錯誤健康情況報告。

如果您需要停用整個 Service Fabric 叢集的 HEALTHCHECK 整合,就必須將 EnableDockerHealthCheckIntegration 設為 false

部署容器應用程式

儲存所有變更,並建置應用程式。 若要發佈您的應用程式,以滑鼠右鍵按一下 [方案總管] 中的 MyFirstContainer,然後選取 [發佈]

在 [連線端點] 中,輸入叢集的管理端點。 例如: containercluster.westus2.cloudapp.azure.com:19000 。 在 Azure 入口網站中,您可以在叢集的 [概觀] 索引標籤中找到用戶端連線端點。

按一下發行

Service Fabric Explorer 是一個 Web 型工具,可檢查和管理 Service Fabric 叢集中的應用程式與節點。 開啟瀏覽器並瀏覽至 http://containercluster.westus2.cloudapp.azure.com:19080/Explorer/ 然後遵循應用程式部署。 此應用程式會進行部署,但在叢集節點中下載映像之前 (視映像大小而定,這可能需要一些時間) 會處於錯誤狀態:Error

應用程式處於 Ready 狀態時便已準備就緒:Ready

開啟瀏覽器並巡覽至 http://containercluster.westus2.cloudapp.azure.com:8081。 您應該會在瀏覽器中看到 "Hello World!" 標題顯示。

清理

當叢集在執行時,您需要繼續支付費用,請考慮刪除您的叢集

將映像推送至容器登錄之後,您可以從開發電腦刪除本機映像︰

docker rmi helloworldapp
docker rmi myregistry.azurecr.io/samples/helloworldapp

Windows Server 容器作業系統和主機作業系統的相容性

Windows Server 容器在主機 OS 的所有版本之間不相容。 例如:

  • 使用 Windows Server 1709 版本所建置的 Windows Server 容器無法在執行 Windows Server 2016 版本的主機上運作。
  • 使用 Windows Server 2016 版本所建置的 Windows Server 容器在執行 Windows Server 1709 版本的主機上只能以 hyperv 隔離模式運作。
  • 透過使用 Windows Server 2016 所建置的 Windows Server 容器,可能必須確保在執行 Windows Server 2016 的主機上以程序隔離模式執行時,容器 OS 和主機 OS 的修訂版本相同。

若要深入了解,請參閱 Windows 容器版本相容性

在建置容器並部署到 Service Fabric 叢集時,請考慮主機 OS 和容器 OS 的相容性。 例如:

  • 請確定您部署的容器具有的 OS 與您叢集節點上的 OS 相容。
  • 請確定為容器應用程式所指定的隔離模式,與其部署所在節點上的容器 OS 支援一致。
  • 請考慮叢集節點或容器的 OS 升級可能會對其相容性造成何種影響。

我們建議您利用下列作法,確定容器已正確部署在 Service Fabric 叢集上:

  • 使用具有 Docker 映像的明確映像標記來指定用於建立容器的 Windows Server OS 版本。
  • 使用您應用程式資訊清單檔案中的 OS 標記,來確定您的應用程式在不同的 Windows Server 版本和升級之間相容。

注意

使用 Service Fabric 6.2 版和更新版本,您可以在 Windows 10 主機上部署以 Windows Server 2016 為基礎的容器。 在 Windows 10 上,不論應用程式資訊清單中所設定的隔離模式為何,容器都會以 Hyper-V 隔離模式執行。 若要深入了解,請參閱設定隔離模式

指定作業系統組建專屬的容器映像

Windows Server 容器在不同的 OS 版本之間可能不相容。 例如,使用 Windows Server 2016 所建置的 Windows Server 容器無法在 Windows Server 1709 版本上以程序隔離模式運作。 因此,如果叢集節點更新為最新版本,則使用較早 OS 版本建置的容器服務可能會失敗。 為了避免執行階段 6.1 版和更新版本發生這種情況,Service Fabric 支援為每個容器指定多個 OS 映像,並以應用程式資訊清單中的 OS 組建版本標記它們。 您可藉由在 Windows 命令提示字元執行 winver 來取得 OS 組建版本。 更新應用程式資訊清單,並指定每個作業系統版本的映像覆寫後,再更新節點上的作業系統。 下列程式碼片段會示範如何在應用程式資訊清單 (ApplicationManifest.xml) 中指定多個容器映像:

      <ContainerHostPolicies> 
         <ImageOverrides> 
	       <Image Name="myregistry.azurecr.io/samples/helloworldappDefault" /> 
               <Image Name="myregistry.azurecr.io/samples/helloworldapp1701" Os="14393" /> 
               <Image Name="myregistry.azurecr.io/samples/helloworldapp1709" Os="16299" /> 
         </ImageOverrides> 
      </ContainerHostPolicies> 

Windows Server 2016 的組建版本為 14393,而 Windows Server 1709 版本的組建版本為 16299。 服務資訊清單可繼續為每個容器服務指定唯一一個映像,如下所示:

<ContainerHost>
    <ImageName>myregistry.azurecr.io/samples/helloworldapp</ImageName> 
</ContainerHost>

注意

作業系統組建版本標記功能只適用於在 Windows 上的 Service Fabric

如果虛擬機器上的基礎作業系統是組建 16299 (1709 版本),Service Fabric 會挑選對應至該版 Windows Server 的容器映像。 如果未標記的容器映像也隨著已標記的容器映像一起提供,則 Service Fabric 會將未標記的映像視為可跨版本使用的其中一個容器映像。 明確地標記容器映像以免在升級期間發生問題。

未標記的容器映會覆寫 ServiceManifest 中提供的映像。 因此映像 "myregistry.azurecr.io/samples/helloworldappDefault" 會覆寫 ServiceManifest 中的 ImageName "myregistry.azurecr.io/samples/helloworldapp"。

完整範例 Service Fabric 應用程式和服務資訊清單

以下是本文中使用的完整服務和應用程式資訊清單。

ServiceManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="Guest1Pkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType.
         The UseImplicitHost attribute indicates this is a guest service. -->
    <StatelessServiceType ServiceTypeName="Guest1Type" UseImplicitHost="true" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <!-- Follow this link for more information about deploying Windows containers to Service Fabric: https://aka.ms/sfguestcontainers -->
      <ContainerHost>
        <ImageName>myregistry.azurecr.io/samples/helloworldapp</ImageName>
        <!-- Pass comma delimited commands to your container: dotnet, myproc.dll, 5" -->
        <!--Commands> dotnet, myproc.dll, 5 </Commands-->
        <Commands></Commands>
      </ContainerHost>
    </EntryPoint>
    <!-- Pass environment variables to your container: -->    
    <EnvironmentVariables>
      <EnvironmentVariable Name="HttpGatewayPort" Value=""/>
      <EnvironmentVariable Name="BackendServiceName" Value=""/>
    </EnvironmentVariables>

  </CodePackage>

  <!-- Config package is the contents of the Config directory under PackageRoot that contains an
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0" />

  <Resources>
    <Endpoints>
      <!-- This endpoint is used by the communication listener to obtain the port on which to
           listen. Please note that if your service is partitioned, this port is shared with
           replicas of different partitions that are placed in your code. -->
      <Endpoint Name="Guest1TypeEndpoint" UriScheme="http" Port="8081" Protocol="http"/>
    </Endpoints>
  </Resources>
</ServiceManifest>

ApplicationManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyFirstContainerType"
                     ApplicationTypeVersion="1.0.0"
                     xmlns="http://schemas.microsoft.com/2011/01/fabric"
                     xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <Parameters>
    <Parameter Name="Guest1_InstanceCount" DefaultValue="-1" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
       should match the Name and Version attributes of the ServiceManifest element defined in the
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
    <EnvironmentOverrides CodePackageRef="FrontendService.Code">
      <EnvironmentVariable Name="HttpGatewayPort" Value="19080"/>
    </EnvironmentOverrides>
    <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <RepositoryCredentials AccountName="myregistry" Password="MIIB6QYJKoZIhvcNAQcDoIIB2jCCAdYCAQAxggFRMIIBTQIBADA1MCExHzAdBgNVBAMMFnJ5YW53aWRhdGFlbmNpcGhlcm1lbnQCEFfyjOX/17S6RIoSjA6UZ1QwDQYJKoZIhvcNAQEHMAAEg
gEAS7oqxvoz8i6+8zULhDzFpBpOTLU+c2mhBdqXpkLwVfcmWUNA82rEWG57Vl1jZXe7J9BkW9ly4xhU8BbARkZHLEuKqg0saTrTHsMBQ6KMQDotSdU8m8Y2BR5Y100wRjvVx3y5+iNYuy/JmM
gSrNyyMQ/45HfMuVb5B4rwnuP8PAkXNT9VLbPeqAfxsMkYg+vGCDEtd8m+bX/7Xgp/kfwxymOuUCrq/YmSwe9QTG3pBri7Hq1K3zEpX4FH/7W2Zb4o3fBAQ+FuxH4nFjFNoYG29inL0bKEcTX
yNZNKrvhdM3n1Uk/8W2Hr62FQ33HgeFR1yxQjLsUu800PrYcR5tLfyTB8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBybgM5NUV8BeetUbMR8mJhgFBrVSUsnp9B8RyebmtgU36dZiSObDsI
NtTvlzhk11LIlae/5kjPv95r3lw6DHmV4kXLwiCNlcWPYIWBGIuspwyG+28EWSrHmN7Dt2WqEWqeNQ==" PasswordEncrypted="true"/>
        <PortBinding ContainerPort="80" EndpointRef="Guest1TypeEndpoint"/>
      </ContainerHostPolicies>
      <ServicePackageResourceGovernancePolicy CpuCores="1"/>
      <ResourceGovernancePolicy CodePackageRef="Code" MemoryInMB="1024"  />
    </Policies>
  </ServiceManifestImport>
  <DefaultServices>
    <!-- The section below creates instances of service types, when an instance of this
         application type is created. You can also create one or more instances of service type using the
         ServiceFabric PowerShell module.

         The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
    <Service Name="Guest1">
      <StatelessService ServiceTypeName="Guest1Type" InstanceCount="[Guest1_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
</ApplicationManifest>

在容器被迫終止前設定時間間隔

您可以在啟動服務刪除 (或移至另一個節點) 之後,設定執行階段在容器移除前所要等候的間隔時間。 設定時間間隔可將 docker stop <time in seconds> 命令傳送至容器。 如需更多詳細資訊,請參閱 docker stop。 所要等候的時間間隔指定於 Hosting 區段之下。 可以在建立叢集時或稍後在設定升級中新增 Hosting 區段。 下列叢集資訊清單程式碼片段示範如何設定等候間隔:

"fabricSettings": [
	...,
	{
        "name": "Hosting",
        "parameters": [
          {
                "name": "ContainerDeactivationTimeout",
                "value" : "10"
          },
	      ...
        ]
	}
]

預設時間間隔會設定為 10 秒。 因為此組態是動態的,所以叢集的僅限組態升級會更新逾時。

將執行階段設定為移除未使用的容器映像

您可以將 Service Fabric 叢集設定為從節點移除未使用的容器映像。 如果節點上存在太多容器映像,此組態允許重新擷取磁碟空間。 若要啟用此功能,請更新叢集資訊清單中的 Hosting 區段,如下列程式碼片段所示:

"fabricSettings": [
	...,
	{
        "name": "Hosting",
        "parameters": [
          {
                "name": "PruneContainerImages",
                "value": "True"
          },
          {
                "name": "ContainerImagesToSkip",
                "value": "mcr.microsoft.com/windows/servercore|mcr.microsoft.com/windows/nanoserver|mcr.microsoft.com/dotnet/framework/aspnet|..."
          }
          ...
          }
        ]
	} 
]

對於不應刪除的映像,您可以在 ContainerImagesToSkip 參數之下加以指定。

設定容器映像下載時間

Service Fabric 執行階段會配置 20 分鐘來下載及擷取容器映像,這適用於大部分的容器映像。 針對大型映像或緩慢的網路連線速度,您可能需要延長中止下載及擷取映像之前的等待時間。 您可以在叢集資訊清單的 Hosting 區段中使用 ContainerImageDownloadTimeout 屬性來設定此逾時,如下列程式碼片段所示:

"fabricSettings": [
	...,
	{
        "name": "Hosting",
        "parameters": [
          {
              "name": "ContainerImageDownloadTimeout",
              "value": "1200"
          }
        ]
	}
]

設定容器保留原則

為了協助診斷容器啟動的失敗情形,Service Fabric (6.1 版或更新版本) 可保留啟動終止或是無法啟動的容器。 此原則可以在 ApplicationManifest.xml 檔案中設定,如下列程式碼片段所示:

 <ContainerHostPolicies CodePackageRef="NodeService.Code" Isolation="process" ContainersRetentionCount="2"  RunInteractive="true"> 

ContainersRetentionCount 設定會指定容器失敗時要保留的容器數目。 如果指定負數值,就會保留所有失敗的容器。 如果未指定 ContainersRetentionCount 屬性,就不會保留任何容器。 ContainersRetentionCount 屬性也支援應用程式參數,因此使用者可以為測試和生產叢集指定不同的值。 使用此功能時,請使用位置限制將容器服務鎖定在特定節點上,以避免容器服務移到其他節點上。 使用此功能的所有容器皆需要手動移除。

使用自訂引數啟動 Docker 精靈

若使用 6.2 版和更新版本的 Service Fabric 執行階段,您可以使用自訂引數啟動 Docker 精靈。 若指定了自訂引數,除了 --pidfile 引數外,Service Fabric 就不會再將任何其他引數傳遞至 Docker 引擎。 因此,不應該將 --pidfile 當作引數來傳遞。 此外,此引數也應該繼續讓 Docker 精靈在 Windows 的預設名稱管道 (若在 Linux 上,則是 Unix 網域通訊端) 上接聽,Service Fabric 才能與精靈通訊。 您可以在叢集資訊清單 [主控] 區段的 ContainerServiceArguments 底下傳遞自訂引數,如下列程式碼片段所示:

"fabricSettings": [
	...,
	{ 
        "name": "Hosting", 
        "parameters": [ 
          { 
            "name": "ContainerServiceArguments", 
            "value": "-H localhost:1234 -H unix:///var/run/docker.sock" 
          } 
        ] 
	} 
]

EntryPoint 覆寫

使用8.2 版的 ServiceFabric 執行時間時,可以覆寫 容器exe 主機 程式碼套件的 entrypoint。 這可以在所有資訊清單專案都維持不變的情況下使用,但需要變更容器映射,然後不再需要布建不同的應用程式類型版本,或必須根據測試或生產案例傳遞不同的引數,而且進入點維持不變。

以下是如何覆寫容器進入點的範例:

ApplicationManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyFirstContainerType"
                     ApplicationTypeVersion="1.0.0"
                     xmlns="http://schemas.microsoft.com/2011/01/fabric"
                     xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <Parameters>
    <Parameter Name="ImageName" DefaultValue="myregistry.azurecr.io/samples/helloworldapp" />
    <Parameter Name="Commands" DefaultValue="commandsOverride" />
    <Parameter Name="FromSource" DefaultValue="sourceOverride" />
    <Parameter Name="EntryPoint" DefaultValue="entryPointOverride" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
       should match the Name and Version attributes of the ServiceManifest element defined in the
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
      <CodePackagePolicy CodePackageRef="Code">
        <EntryPointOverride>
         <ContainerHostOverride>
            <ImageOverrides>
              <Image Name="[ImageName]" />
            </ImageOverrides>
            <Commands>[Commands]</Commands>
            <FromSource>[Source]</FromSource>
            <EntryPoint>[EntryPoint]</EntryPoint>
          </ContainerHostOverride>
        </EntryPointOverride>
      </CodePackagePolicy>
    </Policies>
  </ServiceManifestImport>
</ApplicationManifest>

ServiceManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="Guest1Pkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType.
         The UseImplicitHost attribute indicates this is a guest service. -->
    <StatelessServiceType ServiceTypeName="Guest1Type" UseImplicitHost="true" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <!-- Follow this link for more information about deploying Windows containers to Service Fabric: https://aka.ms/sfguestcontainers -->
      <ContainerHost>
        <ImageName>default imagename</ImageName>
        <Commands>default cmd</Commands>
        <EntryPoint>default entrypoint</EntryPoint>
        <FromSource>default source</FromSource>
      </ContainerHost>
    </EntryPoint>
  </CodePackage>

  <ConfigPackage Name="Config" Version="1.0.0" />
</ServiceManifest>

指定應用程式資訊清單中的覆寫之後,將會啟動映射名稱為 myregistry.azurecr.io/samples/helloworldapp、命令 commandsOverride、來源 sourceOverride 和 entryPoint entryPointOverride 的容器。

同樣地,以下是如何覆寫 ExeHost的範例:

<?xml version="1.0" encoding="utf-8"?>
<Policies>
  <CodePackagePolicy CodePackageRef="Code">
    <EntryPointOverride>
      <ExeHostOverride>
        <Program>[Program]</Program>
        <Arguments>[Entry]</Arguments>
      </ExeHostOverride>
    </EntryPointOverride>
  </CodePackagePolicy>
</Policies>

注意

SetupEntryPoint 不支援進入點覆寫。

下一步