Creare la prima applicazione contenitore di Service Fabric in Windows

Per eseguire un'applicazione esistente in un contenitore Windows in un cluster di Service Fabric non è necessario apportare modifiche all'applicazione. Questo articolo illustra come creare un'immagine Docker contenente un'applicazione Web Python Flask e come distribuirla in un cluster di Azure Service Fabric. Si condividerà anche l'applicazione in contenitore tramite Registro Azure Container. L'articolo presuppone una conoscenza di base di Docker. Per informazioni su Docker, vedere Docker overview (Panoramica su Docker).

Nota

Questo articolo si applica a un ambiente di sviluppo Windows. Il runtime del cluster di Service Fabric e il runtime di Docker devono essere in esecuzione nello stesso sistema operativo. Non è possibile eseguire contenitori Windows su un cluster Linux.

Nota

È consigliabile usare il modulo Azure Az PowerShell per interagire con Azure. Per iniziare, vedere Installare Azure PowerShell. Per informazioni su come eseguire la migrazione al modulo AZ PowerShell, vedere Eseguire la migrazione di Azure PowerShell da AzureRM ad Az.

Prerequisiti

Nota

La distribuzione di contenitori in un cluster di Service Fabric in esecuzione in Windows 10 è supportata. Vedere questo articolo per informazioni su come configurare Windows 10 per l'esecuzione di contenitori Windows.

Nota

Service Fabric versione 6.2 e successive supporta la distribuzione di contenitori in cluster in esecuzione in Windows Server versione 1709.

Definire il contenitore Docker

Compilare un'immagine in base all'immagine Python disponibile nell'hub Docker.

Specificare il contenitore Docker in un Dockerfile. Il Dockerfile è costituito da istruzioni per la configurazione dell'ambiente all'interno del contenitore, il caricamento dell'applicazione da eseguire e il mapping delle porte. Il file Dockerfile rappresenta l'input per il comando docker build che crea l'immagine.

Creare una directory vuota e il file Dockerfile (senza estensione file). Aggiungere quanto segue a Dockerfile e salvare le modifiche:

# 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"]

Per altre informazioni, vedere Dockerfile reference (Informazioni di riferimento su Dockerfile).

Creare un'applicazione Web di base

Creare un'applicazione Web Flask in ascolto sulla porta 80 che restituisce Hello World!. Nella stessa directory creare il file requirements.txt. Aggiungere quanto segue e salvare le modifiche:

Flask

Creare anche il file app.py e aggiungere il frammento di codice seguente:

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)

Accedere a Docker e creare l'immagine

Quindi si creerà l'immagine che esegue l'applicazione Web. Quando si esegue il pull delle immagini pubbliche da Docker (come python:2.7-windowsservercore in Dockerfile), la procedura consigliata consiste nell'eseguire l'autenticazione con l'account Docker Hub invece di effettuare una richiesta pull anonima.

Nota

Quando si effettuano richieste pull anonime frequenti, si potrebbero vedere errori Docker simili a ERROR: toomanyrequests: Too Many Requests. o You have reached your pull rate limit.Esegui l'autenticazione con Docker Hub per evitare questo errore. Per informazioni dettagliate, vedere Gestire il contenuto pubblico con Registro Azure Container.

Aprire una finestra di PowerShell e passare alla directory contenente il Dockerfile. Eseguire quindi i comandi seguenti:

docker login
docker build -t helloworldapp .

Questo comando crea la nuova immagine usando le istruzioni contenute nel Dockerfile e denomina l'immagine helloworldapp, ovvero le assegna un tag -t. Per creare un'immagine del contenitore, l'immagine di base viene prima scaricata dall'hub Docker nel quale viene aggiunta l'applicazione.

Al termine dell'esecuzione del comando di compilazione, eseguire il comando docker images per visualizzare le informazioni sulla nuova immagine:

$ docker images

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

Eseguire l'applicazione in locale

Verifica l'immagine in locale prima di effettuarne il push nel registro contenitori.

Eseguire l'applicazione:

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

name assegna un nome al contenitore in esecuzione, anziché l'ID contenitore.

Dopo aver avviato il contenitore, trovare il relativo indirizzo IP per consentire la connessione al contenitore in esecuzione da un browser:

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

Se il comando non restituisce alcun valore, eseguire il comando seguente ed esaminare l’elemento NetworkSettings->Networks per l’indirizzo IP:

docker inspect my-web-site

Connettersi al contenitore in esecuzione. Aprire un Web browser puntando all'indirizzo IP restituito, ad esempio "http://172.31.194.61"". Nel browser verrà visualizzata l'intestazione "Hello World!".

Per arrestare il contenitore, eseguire:

docker stop my-web-site

Per eliminare il contenitore dal computer di sviluppo, eseguire:

docker rm my-web-site

Effettuare il push dell'immagine nel registro contenitori

Dopo aver verificato l'esecuzione del contenitore nel computer di sviluppo, effettuare il push dell'immagine nel registro all'interno di Registro Azure Container.

Eseguire docker login per accedere al registro contenitori con le credenziali del registro.

Nell’esempio seguente vengono passati l'ID e la password di un'entità servizio di Microsoft Entra. Ad esempio, è possibile che sia stata assegnata un'entità servizio al registro per uno scenario di automazione. In alternativa, è possibile eseguire l'accesso usando il nome utente e la password del registro.

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

Il comando seguente crea un tag, o alias, dell'immagine, con un percorso completo del registro. Questo esempio inserisce l'immagine dello spazio dei nomi samples per evitare confusione nella radice del registro.

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

Effettuare il push dell'immagine nel registro contenitori:

docker push myregistry.azurecr.io/samples/helloworldapp

Creare il servizio in contenitori in Visual Studio

L'SDK e gli strumenti di Service Fabric offrono un modello di servizio che consente di creare un'applicazione in contenitori.

  1. Avviare Visual Studio. Selezionare File>New (Nuovo) >Project (Progetto).
  2. Selezionare l'applicazione di Service Fabric, denominarla "MyFirstContainer" e fare clic su OK.
  3. Scegliere Contenitore dall'elenco dei modelli di servizio.
  4. In Nome immagine immettere "myregistry.azurecr.io/samples/helloworldapp", vale a dire l'immagine di cui è stato effettuato il push nel repository dei contenitori.
  5. Assegnare un nome al servizio e fare clic su OK.

Configurare la comunicazione

Il servizio in contenitori richiede un endpoint per la comunicazione. Aggiungere un elemento Endpoint con il protocollo, la porta e il tipo al file ServiceManifest.xml. In questo esempio viene usata una porta fissa 8081. Se non vengono specificate porte, verrà scelta una porta casuale dall'intervallo di porte dell'applicazione.

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

Nota

È possibile aggiungere altri endpoint per un servizio dichiarando elementi EndPoint aggiuntivi con valori della proprietà applicabili. Ogni porta può dichiarare un solo valore di protocollo.

Definendo un endpoint, Service Fabric pubblica l'endpoint nel servizio Naming. Altri servizi in esecuzione nel cluster possono risolvere questo contenitore. È anche possibile eseguire la comunicazione da contenitore a contenitore usando il proxy inverso. La comunicazione avviene specificando la porta di ascolto HTTP del proxy inverso e il nome dei servizi con cui si vuole comunicare come variabili di ambiente.

Il servizio è in ascolto su una porta specifica, 8081 in questo esempio. Quando l'applicazione viene distribuita in un cluster in Azure, sia il cluster che l'applicazione vengono eseguiti dietro un servizio di bilanciamento del carico di Azure. La porta dell'applicazione deve essere aperta nel servizio di bilanciamento del carico di Azure in modo che il traffico in entrata possa raggiungere il servizio. È possibile aprire questa porta nel servizio di bilanciamento carico di Azure usando uno script di PowerShell o il portale di Azure.

Configurare e impostare variabili di ambiente

È possibile specificare variabili di ambiente per ogni pacchetto di codice nel manifesto del servizio. Questa funzionalità è disponibile per tutti i servizi, siano essi distribuiti come contenitori, processi o eseguibili guest. È possibile sostituire i valori delle variabili di ambiente nel manifesto dell'applicazione oppure specificarli durante la distribuzione come parametri dell'applicazione.

Il frammento XML del manifesto del servizio seguente offre un esempio di come specificare le variabili di ambiente per un pacchetto di codice:

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

È possibile eseguire l'override di queste variabili di ambiente nel manifesto dell'applicazione:

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

Configurare il mapping tra porta del contenitore e porta dell'host e l'individuazione da contenitore a contenitore

Configurare una porta dell'host per la comunicazione con il contenitore. Il binding di porta esegue il mapping tra la porta su cui il servizio è in ascolto nel contenitore e una porta nell'host. Aggiungere un elemento PortBinding nell'elemento ContainerHostPolicies del file ApplicationManifest.xml. Per questo articolo, il valore di ContainerPort è 80, vale a dire che il contenitore espone la porta 80, come specificato nel Dockerfile, e il valore di EndpointRef è "Guest1TypeEndpoint", ovvero l'endpoint definito in precedenza nel manifesto del servizio. Per le richieste in ingresso per il servizio sulla porta 8081 viene eseguito il mapping alla porta 80 del contenitore.

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

Nota

È possibile aggiungere altri PortBinding per un servizio dichiarando elementi PortBinding aggiuntivi con valori della proprietà applicabili.

Configurare l'autenticazione del repository di contenitori

Vedere Autenticazione del repository contenitoreper scoprire come configurare tipi di autenticazione diversi per il download dell'immagine del contenitore.

Configurare la modalità di isolamento

Windows supporta due modalità di isolamento per i contenitori: la modalità processo e la modalità Hyper-V. Nella modalità di isolamento del processo tutti i contenitori in esecuzione nello stesso computer host condividono il kernel con l'host. Nella modalità di isolamento Hyper-V i kernel sono isolati tra i singoli contenitori Hyper-V e il contenitore host. La modalità di isolamento è specificata nell'elemento ContainerHostPolicies nel file manifesto dell'applicazione. Le modalità di isolamento specificabili sono process, hyperv e default. L'impostazione predefinita è la modalità di isolamento dei processi negli host Windows Server. Negli host Windows 10 è supportata solo la modalità di isolamento Hyper-V, pertanto il contenitore verrà eseguito in modalità di isolamento Hyper-V indipendentemente dalla modalità di isolamento impostata. Il frammento seguente indica come è specificata la modalità di isolamento nel file manifesto dell'applicazione.

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

Nota

La modalità di isolamento Hyper-V è disponibile negli SKU di Azure Ev3 e Dv3 che hanno il supporto per la virtualizzazione annidato.

Configurare la governance delle risorse

La governance delle risorse limita le risorse che possono essere usate dal contenitore nell'host. L'elemento ResourceGovernancePolicy, specificato nel manifesto dell'applicazione, viene usato per dichiarare limiti di risorse per il pacchetto di codice di un servizio. È possibile impostare limiti per le risorse seguenti: Memory, MemorySwap, CpuShares (peso relativo CPU), MemoryReservationInMB, BlkioWeight (peso relativo BlockIO). In questo esempio, il pacchetto del servizio Guest1Pkg ottiene un core nei nodi del cluster in cui è posizionato. I limiti di memoria sono assoluti, quindi i pacchetti di codice sono limitati a 1024 MB di memoria, con prenotazione a garanzia flessibile. I pacchetti di codice (contenitori o pacchetti) non sono in grado di allocare una quantità di memoria superiore a questo limite. Un'operazione di questo tipo genererebbe un'eccezione di memoria esaurita. Perché l'imposizione di un limite di risorse funzioni, è necessario che tutti i pacchetti di codice inclusi in un pacchetto del servizio abbiano limiti di memoria specificati.

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

Configurare docker HEALTHCHECK

A partire dalla versione 6.1, Service Fabric integra automaticamente gli eventi di docker HEALTHCHECK nel report relativo all'integrità del sistema. Se HEALTHCHECK è stato abilitato nel contenitore, Service Fabric fornirà informazioni sull'integrità ogni volta che lo stato dell'integrità del contenitore subisce modifiche, in base a quanto segnalato da Docker. Un report sull'integrità di tipo OK verrà visualizzato in Service Fabric Explorer quando il valore health_status è healthy e un report di tipo AVVISO verrà visualizzato quando il valore health_status è unhealthy.

A partire dall'aggiornamento più recente della versione v6.4, è possibile specificare che le valutazioni HEALTHCHECK Docker devono essere segnalate come un errore. Se questa opzione è abilitata, verrà visualizzato un report sull'integrità OK quando health_status è healthy, mentre verrà visualizzato ERRORE quando health_status è unhealthy.

L'istruzione HEALTHCHECK che fa riferimento alla verifica effettiva eseguita per il monitoraggio dell'integrità dei contenitori deve essere presente nel Dockerfile usato durante la generazione dell'immagine del contenitore.

Screenshot che mostra i dettagli del pacchetto del servizio distribuito NodeServicePackage.

HealthCheckUnhealthyApp

HealthCheckUnhealthyDsp

È possibile configurare il comportamento di HEALTHCHECK per ogni contenitore specificando le opzioni di HealthConfig come parte di ContainerHostPolicies in ApplicationManifest.

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

Per impostazione predefinita, l'opzione IncludeDockerHealthStatusInSystemHealthReport è impostata su true, l'opzione RestartContainerOnUnhealthyDockerHealthStatus è impostata su false e l'opzione TreatContainerUnhealthyStatusAsError è impostata su false.

Se l'opzione RestartContainerOnUnhealthyDockerHealthStatus è impostata su true, un contenitore che segnala ripetutamente uno stato non integro viene riavviato, possibilmente su altri nodi.

Se TreatContainerUnhealthyStatusAsError è impostato su true, i report sull'integrità ERRORE verranno visualizzati quando health_status del contenitore è unhealthy.

Se si vuole disabilitare l'integrazione di HEALTHCHECK per l'intero cluster di Service Fabric, sarà necessario impostare EnableDockerHealthCheckIntegration su false.

Distribuire l'applicazione del contenitore

Salvare tutte le modifiche e compilare l'applicazione. Per pubblicare l'applicazione, fare clic con il pulsante destro del mouse su MyFirstContainer in Esplora soluzioni e scegliere Pubblica.

In Endpoint connessione immettere l'endpoint di gestione per il cluster, Ad esempio, containercluster.westus2.cloudapp.azure.com:19000. L'endpoint di connessione del client è disponibile nella scheda Panoramica del cluster nel portale di Azure.

Fare clic su Pubblica.

Service Fabric Explorer è uno strumento basato sul Web che permette di analizzare e gestire applicazioni e nodi in un cluster di Service Fabric. Aprire un browser Web e passare a http://containercluster.westus2.cloudapp.azure.com:19080/Explorer/ per seguire la distribuzione dell'applicazione. L'applicazione viene distribuita, ma rimane in stato di errore fino a quando l'immagine non viene scaricata nei nodi del cluster. Tale operazione può richiedere del tempo, a seconda delle dimensioni dell'immagine: Error

L'applicazione è pronta quando il suo stato è Ready: Pronto

Aprire un browser e passare a http://containercluster.westus2.cloudapp.azure.com:8081. Nel browser verrà visualizzata l'intestazione "Hello World!".

Eseguire la pulizia

Mentre il cluster è in esecuzione, continuano a essere addebitati i relativi costi. È quindi consigliabile eliminare il cluster.

Dopo aver effettuato il push dell'immagine nel registro contenitori, è possibile eliminare l'immagine locale dal computer di sviluppo:

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

Compatibilità tra il sistema operativo del contenitore di Windows Server e il sistema operativo dell'host

I contenitori di Windows Server non sono compatibili con tutte le versioni del sistema operativo host. Ad esempio:

  • I contenitori di Windows Server creati tramite Windows Server versione 1709 non funzionano in un host che esegue Windows Server 2016.
  • I contenitori di Windows Server creati tramite Windows Server 2016 funzionano in modalità di isolamento Hyper-V solo in un host che esegue Windows Server versione 1709.
  • Con i contenitori di Windows Server creati tramite Windows Server 2016, potrebbe essere necessario assicurarsi che la revisione del sistema operativo del contenitore e del sistema operativo host corrispondano durante l'esecuzione in modalità di isolamento dei processi in un host che esegue Windows Server 2016.

Per altre informazioni, vedere Compatibilità delle versioni dei contenitori di Windows.

Considerare la compatibilità del sistema operativo host e del sistema operativo del contenitore durante la creazione e la distribuzione dei contenitori nel cluster di Service Fabric. Ad esempio:

  • Assicurarsi di distribuire i contenitori con un sistema operativo compatibile con il sistema operativo nei nodi del cluster.
  • Assicurarsi che la modalità di isolamento specificata per l'applicazione contenitore sia coerente con il supporto per il sistema operativo del contenitore nel nodo in cui viene distribuito.
  • Valutare in che modo gli aggiornamenti del sistema operativo nei nodi del cluster o nei contenitori possono influenzarne la compatibilità.

È consigliabile attenersi alle seguenti procedure per assicurarsi che i contenitori siano distribuiti correttamente nel cluster di Service Fabric:

  • Usare l'assegnazione di tag espliciti con le immagini Docker per specificare la versione del sistema operativo Windows Server da cui è stato creato un contenitore.
  • Usare l'assegnazione di tag del sistema operativo nel file manifesto dell'applicazione per assicurarsi che l'applicazione sia compatibile con le diverse versioni e gli aggiornamenti di Windows Server.

Nota

Con Service Fabric 6.2 e versioni successive, è possibile distribuire i contenitori basati su Windows Server 2016 in locale su un host Windows 10. In Windows 10, i contenitori vengono eseguiti in modalità di isolamento Hyper-V, indipendentemente dalla modalità di isolamento impostata nel manifesto dell'applicazione. Per altre informazioni, vedere Configurare la modalità di isolamento.

Specificare immagini del contenitore specifiche per la build del sistema operativo

I contenitori di Windows Server potrebbero non essere compatibili nelle diverse versioni del sistema operativo. Ad esempio, i contenitori di Windows Server creati tramite Windows Server 2016 non funzionano in Windows Server versione 1709 in modalità di isolamento dei processi. Se i nodi del cluster vengono aggiornati alla versione più recente, è quindi possibile che si verifichino errori nei servizi contenitori creati usando le versioni precedenti del sistema operativo. Per aggirare questo problema con la versione 6.1 del runtime e con le versioni successive, Service Fabric supporta la possibilità di specificare più immagini del sistema operativo per ogni contenitore e di contrassegnarle con le versioni della build del sistema operativo nel manifesto dell'applicazione. È possibile ottenere la versione della build del sistema operativo eseguendo winver al prompt dei comandi di Windows. Aggiornare i manifesti dell'applicazione e specificare gli override delle immagini per ogni versione del sistema operativo prima di aggiornare il sistema operativo nei nodi. Il frammento di codice seguente mostra come specificare più immagini del contenitore nel manifesto dell'applicazione, 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> 

La versione della build per Windows Server 2016 è 14393 e la versione della build per Windows Server versione 1709 è 16299. Il manifesto del servizio continua a specificare solo un'immagine per ogni servizio contenitore, come mostrato di seguito:

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

Nota

Le funzionalità di contrassegno delle versioni della build del sistema operativo sono disponibili solo per Service Fabric su Windows

Se la build del sistema operativo sottostante sulla VM è 16299 (versione 1709), Service Fabric seleziona l'immagine del contenitore corrispondente a tale versione di Windows Server. Se nel manifesto dell'applicazione viene fornita anche un'immagine del contenitore non contrassegnata insieme alle immagini del contenitore contrassegnate, Service Fabric considera l'immagine non contrassegnata come quella in grado di funzionare in tutte le versioni. Contrassegnare le immagini del contenitore in modo esplicito per evitare problemi durante gli aggiornamenti.

L'immagine del contenitore non contrassegnata eseguirà l'override dell'immagine specificata nel file ServiceManifest. L'immagine "myregistry.azurecr.io/samples/helloworldappDefault" eseguirà quindi l'override del nome immagine "myregistry.azurecr.io/samples/helloworldapp" nel file ServiceManifest.

Manifesti di esempio completi del servizio e dell'applicazione di Service Fabric

Di seguito sono riportati i manifesti completi del servizio e dell'applicazione usati in questo articolo.

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>

Configurare l'intervallo di tempo prima della terminazione forzata del contenitore

È possibile configurare un intervallo di tempo di attesa del runtime prima che il contenitore venga rimosso dopo l'avvio dell'eliminazione del servizio (o di un passaggio a un altro nodo). Configurando l'intervallo di tempo, viene inviato il comando docker stop <time in seconds> al contenitore. Per altri dettagli, vedere docker stop. L'intervallo di tempo per l'attesa viene specificato nella sezione Hosting. È possibile aggiungere la sezione Hosting al momento della creazione del cluster o successivamente durante un aggiornamento della configurazione. Il frammento di manifesto del cluster seguente illustra come impostare l'intervallo di attesa:

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

L'intervallo di tempo predefinito è impostato su 10 secondi. Poiché questa configurazione è dinamica, un aggiornamento della sola configurazione nel cluster aggiorna il timeout.

Configurare il runtime per rimuovere le immagini del contenitore non usate

È possibile configurate il cluster di Service Fabric per rimuovere le immagini del contenitore non usate dal nodo. Questa configurazione consente di riacquisire spazio su disco se nel nodo sono presenti troppe immagini del contenitore. Per abilitare questa funzionalità, aggiornare la sezione Hosting nel manifesto del cluster, come illustrato nel frammento di codice seguente:

"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|..."
          }
          ...
          }
        ]
	} 
]

Le immagini che non devono essere eliminate possono essere specificate nel parametro ContainerImagesToSkip.

Configurare il tempo di download delle immagini del contenitore

Il runtime di Service Fabric alloca 20 minuti per il download e l'estrazione delle immagini del contenitore, perché tale limite è appropriato per la maggior parte delle immagini del contenitore. Per immagini di grandi dimensioni o in caso di connessione di rete lenta potrebbe essere necessario aumentare il tempo di attesa prima dell'interruzione del download e dell'estrazione dell'immagine. Questo timeout viene configurato tramite l'attributo ContainerImageDownloadTimeout nella sezione Hosting del manifesto del cluster, come mostrato nel frammento di codice seguente:

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

Configurare i criteri di conservazione dei contenitori

Per semplificare la diagnosi degli errori di avvio dei contenitori, Service Fabric (versione 6.1 o versioni successive) supporta la conservazione di contenitori terminati o il cui avvio non è riuscito. Questo criterio può essere configurato nel file ApplicationManifest.xml, come mostrato nel frammento di codice seguente:

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

L'impostazione ContainersRetentionCount specifica il numero di contenitori da conservare in caso di errore. Se viene specificato un valore negativo, verranno conservati tutti i contenitori con errori. Quando l'attributo ContainersRetentionCount non viene specificato, non verrà conservato alcun contenitore. L'attributo ContainersRetentionCount supporta anche i parametri dell'applicazione, quindi gli utenti possono specificare valori diversi per cluster di test e di produzione. Usare vincoli di posizionamento per specificare come destinazione un nodo specifico per il servizio contenitore quando si usa questa funzionalità, per evitare che il servizio contenitore passi ad altri nodi. Eventuali contenitori conservati tramite questa funzionalità devono essere rimossi manualmente.

Avviare il daemon Docker con argomenti personalizzati

A partire dalla versione 6.2 del runtime di Service Fabric è possibile avviare il daemon Docker con argomenti personalizzati. Quando vengono specificati argomenti personalizzati, Service Fabric non passa altri argomenti al motore Docker, ad eccezione dell'argomento --pidfile. Di conseguenza, --pidfile non deve essere passato come argomento. L'argomento deve continuare ad avere il daemon Docker in ascolto sulla named pipe predefinita in Windows (o sul socket di dominio Unix in Linux) perché Service Fabric possa comunicare con il daemon. Gli argomenti personalizzati vengono passati nel manifesto del cluster nella sezione Hosting in ContainerServiceArguments, come mostrato nel frammento di codice seguente:

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

Override del punto di ingresso

Con la versione 8.2 di ServiceFabric Runtime, è possibile eseguire l'override del punto di ingresso per il contenitore e il pacchetto di codice ExeHost. Questa operazione può essere usata nei casi in cui tutti gli elementi manifesto rimangano invariati, ma è necessario modificare l'immagine del contenitore. In tal caso, il provisioning di una versione diversa del tipo di app non è più necessario oppure è necessario passare argomenti diversi in base allo scenario di test o di produzione e il punto di ingresso rimane invariato.

Di seguito è riportato un esempio di come eseguire l'override del punto di ingresso del contenitore:

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>

Dopo aver specificato le sostituzioni dell’applicazione nel manifesto, verrà avviato il contenitore con nome immagine myregistry.azurecr.io/samples/helloworldapp, comando commandsOverride, origine sourceOverride e punto di ingresso entryPointOverride.

Analogamente, di seguito è riportato un esempio di come eseguire l'override di ExeHost:

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

Nota

L'override del punto di ingresso non è supportato per SetupEntryPoint.

Passaggi successivi