Creare la prima applicazione contenitore di Service Fabric in WindowsCreate your first Service Fabric container application on Windows

Per eseguire un'applicazione esistente in un contenitore Windows in un cluster di Service Fabric non è necessario apportare modifiche all'applicazione.Running an existing application in a Windows container on a Service Fabric cluster doesn't require any changes to your application. Questo articolo illustra come creare un'immagine Docker contenente un'applicazione Web Python Flask e come distribuirla in un cluster di Service Fabric.This article walks you through creating a Docker image containing a Python Flask web application and deploying it to a Service Fabric cluster. Si condividerà anche l'applicazione in contenitore tramite Registro contenitori di Azure.You will also share your containerized application through Azure Container Registry. L'articolo presuppone una conoscenza di base di Docker.This article assumes a basic understanding of Docker. Per informazioni su Docker, vedere Docker overview (Panoramica su Docker).You can learn about Docker by reading the Docker Overview.

PrerequisitiPrerequisites

Un computer di sviluppo che esegue:A development computer running:

  • Visual Studio 2015 o Visual Studio 2017.Visual Studio 2015 or Visual Studio 2017.
  • SDK e strumenti di Service Fabric.Service Fabric SDK and tools.
  • Docker per Windows.Docker for Windows. Scaricare Docker CE per Windows (stabile).Get Docker CE for Windows (stable). Dopo aver installato e avviato Docker, fare clic con il pulsante destro del mouse sull'icona nell'area di notifica e selezionare Switch to Windows containers (Passa ai contenitori Windows).After installing and starting Docker, right-click on the tray icon and select Switch to Windows containers. Questa operazione è necessaria per eseguire le immagini Docker basate su Windows.This is required to run Docker images based on Windows.

Un cluster di Windows con tre o più nodi in esecuzione in Windows Server 2016 con Contenitori. A questo scopo, creare un cluster o provare Service Fabric gratuitamente.A Windows cluster with three or more nodes running on Windows Server 2016 with Containers- Create a cluster or try Service Fabric for free.

Un registro all'interno del registro contenitori di Azure. A questo scopo, creare un registro contenitori nella sottoscrizione di Azure.A registry in Azure Container Registry - Create a container registry in your Azure subscription.

Definire il contenitore DockerDefine the Docker container

Compilare un'immagine in base all'immagine Python disponibile nell'hub Docker.Build an image based on the Python image located on Docker Hub.

Definire il contenitore Docker in un Dockerfile.Define your Docker container in a Dockerfile. Il Dockerfile contiene istruzioni per la configurazione dell'ambiente all'interno del contenitore, il caricamento dell'applicazione da eseguire e il mapping delle porte.The Dockerfile contains instructions for setting up the environment inside your container, loading the application you want to run, and mapping ports. Il file Dockerfile rappresenta l'input per il comando docker build che crea l'immagine.The Dockerfile is the input to the docker build command, which creates the image.

Creare una directory vuota e il file Dockerfile (senza estensione file).Create an empty directory and create the file Dockerfile (with no file extension). Aggiungere quanto segue a Dockerfile e salvare le modifiche:Add the following to Dockerfile and save your changes:

# 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).Read the Dockerfile reference for more information.

Creare un'applicazione Web sempliceCreate a simple web application

Creare un'applicazione Web Flask in ascolto sulla porta 80 che restituisce "Hello World!".Create a Flask web application listening on port 80 that returns "Hello World!". Nella stessa directory creare il file requirements.txt.In the same directory, create the file requirements.txt. Aggiungere quanto segue e salvare le modifiche:Add the following and save your changes:

Flask

Creare anche il file app.py e aggiungere quanto segue:Also create the app.py file and add the following:

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)

Compilare l'immagineBuild the image

Eseguire il comando docker build per creare l'immagine che esegue l'applicazione Web.Run the docker build command to create the image that runs your web application. Aprire una finestra di PowerShell e passare alla directory contenente il Dockerfile.Open a PowerShell window and navigate to the directory containing the Dockerfile. Eseguire il comando seguente:Run the following command:

docker build -t helloworldapp .

Questo comando compila la nuova immagine usando le istruzioni contenute nel file Dockerfile e denomina l'immagine "helloworldapp" , ovvero le assegna un tag -t.This command builds the new image using the instructions in your Dockerfile, naming (-t tagging) the image "helloworldapp". La compilazione di un'immagine determina il pull dell'immagine di base dall'hub Docker e la creazione di una nuova immagine che aggiunge l'applicazione sopra l'immagine di base.Building an image pulls the base image down from Docker Hub and creates a new image that adds your application on top of the base image.

Al termine dell'esecuzione del comando di compilazione, eseguire il comando docker images per visualizzare le informazioni sulla nuova immagine:Once the build command completes, run the docker images command to see information on the new image:

$ docker images

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

Eseguire l'applicazione in localeRun the application locally

Verifica l'immagine in locale prima di effettuarne il push nel registro contenitori.Verify your image locally before pushing it the container registry.

Eseguire l'applicazione:Run the application:

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

name assegna un nome al contenitore in esecuzione, anziché l'ID contenitore.name gives a name to the running container (instead of the container ID).

Dopo aver avviato il contenitore, trovare il relativo indirizzo IP per consentire la connessione al contenitore in esecuzione da un browser:Once the container starts, find its IP address so that you can connect to your running container from a browser:

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

Connettersi al contenitore in esecuzione.Connect to the running container. Aprire un Web browser puntando all'indirizzo IP restituito, ad esempio "http://172.31.194.61".Open a web browser pointing to the IP address returned, for example "http://172.31.194.61". Verrà visualizzata l'intestazione "Hello World!"You should see the heading "Hello World!" nel browser.display in the browser.

Per arrestare il contenitore, eseguire:To stop your container, run:

docker stop my-web-site

Per eliminare il contenitore dal computer di sviluppo, eseguire:Delete the container from your development machine:

docker rm my-web-site

Effettuare il push dell'immagine nel registro contenitoriPush the image to the container registry

Dopo aver verificato l'esecuzione del contenitore nel computer di sviluppo, effettuare il push dell'immagine nel registro all'interno del registro contenitori di Azure.After you verify that the container runs on your development machine, push the image to your registry in Azure Container Registry.

Eseguire docker login per accedere al registro di contenitori con le credenziali del registro.Run docker login to log in to your container registry with your registry credentials.

L'esempio seguente passa l'ID e la password di un'entità servizio di Azure Active Directory.The following example passes the ID and password of an Azure Active Directory service principal. Ad esempio, è possibile che sia stata assegnata un'entità servizio al registro per uno scenario di automazione.For example, you might have assigned a service principal to your registry for an automation scenario. In alternativa, è possibile eseguire l'accesso usando il nome utente e la password del registro.Or, you could login using your registry username and password.

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.The following command creates a tag, or alias, of the image, with a fully qualified path to your registry. Questo esempio inserisce l'immagine dello spazio dei nomi samples per evitare confusione nella radice del registro.This example places the image in the samples namespace to avoid clutter in the root of the registry.

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

Effettuare il push dell'immagine nel registro contenitori:Push the image to your container registry:

docker push myregistry.azurecr.io/samples/helloworldapp

Creare il servizio in contenitori in Visual StudioCreate the containerized service in Visual Studio

L'SDK e gli strumenti di Service Fabric offrono un modello di servizio che consente di creare un'applicazione in contenitori.The Service Fabric SDK and tools provide a service template to help you create a containerized application.

  1. Avviare Visual Studio.Start Visual Studio. Selezionare File > Nuovo > Progetto.Select File > New > Project.
  2. Selezionare l'applicazione di Service Fabric, denominarla "MyFirstContainer" e fare clic su OK.Select Service Fabric application, name it "MyFirstContainer", and click OK.
  3. Scegliere Contenitore dall'elenco dei modelli di servizio.Select Container from the list of service templates.
  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.In Image Name enter "myregistry.azurecr.io/samples/helloworldapp", the image you pushed to your container repository.
  5. Assegnare un nome al servizio e fare clic su OK.Give your service a name, and click OK.

Configurare la comunicazioneConfigure communication

Il servizio in contenitori richiede un endpoint per la comunicazione.The containerized service needs an endpoint for communication. Aggiungere un elemento Endpoint con il protocollo, la porta e il tipo al file ServiceManifest.xml.Add an Endpoint element with the protocol, port, and type to the ServiceManifest.xml file. Per questo articolo, il servizio in contenitori è in ascolto sulla porta 8081.For this article, the containerized service listens on port 8081. In questo esempio viene usata una porta fissa 8081.In this example, a fixed port 8081 is used. Se non vengono specificate porte, verrà scelta una porta casuale dall'intervallo di porte dell'applicazione.If no port is specified, a random port from the application port range is chosen.

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

Definendo un endpoint, Service Fabric pubblica l'endpoint nel servizio Naming.By defining an endpoint, Service Fabric publishes the endpoint to the Naming service. Altri servizi in esecuzione nel cluster possono risolvere questo contenitore.Other services running in the cluster can resolve this container. È anche possibile eseguire la comunicazione da contenitore a contenitore usando il proxy inverso.You can also perform container-to-container communication using the reverse proxy. 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.Communication is performed by providing the reverse proxy HTTP listening port and the name of the services that you want to communicate with as environment variables.

Configurare e impostare variabili di ambienteConfigure and set environment variables

È possibile specificare variabili di ambiente per ogni pacchetto di codice nel manifesto del servizio.Environment variables can be specified for each code package in the service manifest. Questa funzionalità è disponibile per tutti i servizi, siano essi distribuiti come contenitori, processi o eseguibili guest.This feature is available for all services irrespective of whether they are deployed as containers or processes or guest executables. È possibile sostituire i valori delle variabili di ambiente nel manifesto dell'applicazione oppure specificarli durante la distribuzione come parametri dell'applicazione.You can override environment variable values in the application manifest or specify them during deployment as application parameters.

Il frammento XML del manifesto del servizio seguente offre un esempio di come specificare le variabili di ambiente per un pacchetto di codice:The following service manifest XML snippet shows an example of how to specify environment variables for a code package:

<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:These environment variables can be overridden in the application manifest:

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

Configurare il mapping tra porta del contenitore e porta dell'host e l'individuazione da contenitore a contenitoreConfigure container port-to-host port mapping and container-to-container discovery

Configurare una porta dell'host per la comunicazione con il contenitore.Configure a host port used to communicate with the container. Il binding di porta esegue il mapping tra la porta su cui il servizio è in ascolto nel contenitore e una porta nell'host.The port binding maps the port on which the service is listening inside the container to a port on the host. Aggiungere un elemento PortBinding nell'elemento ContainerHostPolicies del file ApplicationManifest.xml.Add a PortBinding element in ContainerHostPolicies element of the ApplicationManifest.xml file. 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.For this article, ContainerPort is 80 (the container exposes port 80, as specified in the Dockerfile) and EndpointRef is "Guest1TypeEndpoint" (the endpoint previously defined in the service manifest). Per le richieste in ingresso per il servizio sulla porta 8081 viene eseguito il mapping alla porta 80 del contenitore.Incoming requests to the service on port 8081 are mapped to port 80 on the container.

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

Configurare l'autenticazione del registro contenitoriConfigure container registry authentication

Configurare l'autenticazione del registro contenitori aggiungendo RepositoryCredentials a ContainerHostPolicies nel file ApplicationManifest.xml.Configure container registry authentication by adding RepositoryCredentials to ContainerHostPolicies of the ApplicationManifest.xml file. Aggiungere l'account e la password per il contenitore myregistry.azurecr.io, per consentire al servizio di scaricare l'immagine del contenitore dal repository.Add the account and password for the myregistry.azurecr.io container registry, which allows the service to download the container image from the repository.

<Policies>
    <ContainerHostPolicies CodePackageRef="Code">
        <RepositoryCredentials AccountName="myregistry" Password="=P==/==/=8=/=+u4lyOB=+=nWzEeRfF=" PasswordEncrypted="false"/>
        <PortBinding ContainerPort="80" EndpointRef="Guest1TypeEndpoint"/>
    </ContainerHostPolicies>
</Policies>

È consigliabile crittografare la password del repository con un certificato di crittografia distribuito in tutti i nodi del cluster.We recommend that you encrypt the repository password by using an encipherment certificate that's deployed to all nodes of the cluster. Quando Service Fabric distribuisce il pacchetto del servizio nel cluster, il certificato di crittografia viene usato per decrittografare il testo crittografato.When Service Fabric deploys the service package to the cluster, the encipherment certificate is used to decrypt the cipher text. Il cmdlet Invoke-ServiceFabricEncryptText viene usato per creare il testo crittografato della password, che viene aggiunto al file ApplicationManifest.xml.The Invoke-ServiceFabricEncryptText cmdlet is used to create the cipher text for the password, which is added to the ApplicationManifest.xml file.

Lo script seguente crea un nuovo certificato autofirmato e lo esporta in un file PFX.The following script creates a new self-signed certificate and exports it to a PFX file. Il certificato viene importato in un insieme di credenziali delle chiavi esistente e quindi distribuito nel cluster di Service Fabric.The certificate is imported into an existing key vault and then deployed to the Service Fabric cluster.

# Variables.
$certpwd = ConvertTo-SecureString -String "Pa$$word321!" -Force -AsPlainText
$filepath = "C:\MyCertificates\dataenciphermentcert.pfx"
$subjectname = "dataencipherment"
$vaultname = "mykeyvault"
$certificateName = "dataenciphermentcert"
$groupname="myclustergroup"
$clustername = "mycluster"

$subscriptionId = "subscription ID"

Login-AzureRmAccount

Select-AzureRmSubscription -SubscriptionId $subscriptionId

# Create a self signed cert, export to PFX file.
New-SelfSignedCertificate -Type DocumentEncryptionCert -KeyUsage DataEncipherment -Subject $subjectname -Provider 'Microsoft Enhanced Cryptographic Provider v1.0' `
| Export-PfxCertificate -FilePath $filepath -Password $certpwd

# Import the certificate to an existing key vault.  The key vault must be enabled for deployment.
$cer = Import-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName -FilePath $filepath -Password $certpwd

Set-AzureRmKeyVaultAccessPolicy -VaultName $vaultName -ResourceGroupName $groupname -EnabledForDeployment

# Add the certificate to all the VMs in the cluster.
Add-AzureRmServiceFabricApplicationCertificate -ResourceGroupName $groupname -Name $clustername -SecretIdentifier $cer.SecretId

Crittografare la password usando il cmdlet Invoke-ServiceFabricEncryptText.Encrypt the password using the Invoke-ServiceFabricEncryptText cmdlet.

$text = "=P==/==/=8=/=+u4lyOB=+=nWzEeRfF="
Invoke-ServiceFabricEncryptText -CertStore -CertThumbprint $cer.Thumbprint -Text $text -StoreLocation Local -StoreName My

Sostituire la password con il testo crittografato restituito dal cmdlet Invoke-ServiceFabricEncryptText e impostare PasswordEncrypted su "true".Replace the password with the cipher text returned by the Invoke-ServiceFabricEncryptText cmdlet and set PasswordEncrypted to "true".

<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>
</Policies>

Configurare la modalità di isolamentoConfigure isolation mode

Windows supporta due modalità di isolamento per i contenitori: la modalità processo e la modalità Hyper-V.Windows supports two isolation modes for containers: process and Hyper-V. Nella modalità di isolamento del processo tutti i contenitori in esecuzione nello stesso computer host condividono il kernel con l'host.With the process isolation mode, all the containers running on the same host machine share the kernel with the host. Nella modalità di isolamento Hyper-V i kernel sono isolati tra i singoli contenitori Hyper-V e il contenitore host.With the Hyper-V isolation mode, the kernels are isolated between each Hyper-V container and the container host. La modalità di isolamento è specificata nell'elemento ContainerHostPolicies nel file manifesto dell'applicazione.The isolation mode is specified in the ContainerHostPolicies element in the application manifest file. Le modalità di isolamento specificabili sono process, hyperv e default.The isolation modes that can be specified are process, hyperv, and default. La modalità di isolamento assume come impostazione predefinita process negli host Windows Server e hyperv negli host Windows 10.The default isolation mode defaults to process on Windows Server hosts, and defaults to hyperv on Windows 10 hosts. Il frammento seguente indica come è specificata la modalità di isolamento nel file manifesto dell'applicazione.The following snippet shows how the isolation mode is specified in the application manifest file.

<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.The hyperv isolation mode is available on Ev3 and Dv3 Azure SKUs which have nested virtualization support. Verificare che il ruolo Hyper-V sia installato negli host.Ensure the hyperv role is installed on the hosts. A tale scopo, connettersi agli host.Verify this by connecting to the hosts.

Configurare la governance delle risorseConfigure resource governance

La governance delle risorse limita le risorse che possono essere usate dal contenitore nell'host.Resource governance restricts the resources that the container can use on the host. L'elemento ResourceGovernancePolicy, specificato nel manifesto dell'applicazione, viene usato per dichiarare limiti di risorse per il pacchetto di codice di un servizio.The ResourceGovernancePolicy element, which is specified in the application manifest, is used to declare resource limits for a service code package. È possibile impostare limiti per le risorse seguenti: Memory, MemorySwap, CpuShares (peso relativo CPU), MemoryReservationInMB, BlkioWeight (peso relativo BlockIO).Resource limits can be set for the following resources: Memory, MemorySwap, CpuShares (CPU relative weight), MemoryReservationInMB, BlkioWeight (BlockIO relative weight). In questo esempio, il pacchetto del servizio Guest1Pkg ottiene un core nei nodi del cluster in cui è posizionato.In this example, service package Guest1Pkg gets one core on the cluster nodes where it is placed. I limiti di memoria sono assoluti, quindi i pacchetti di codice sono limitati a 1024 MB di memoria, con prenotazione a garanzia flessibile.Memory limits are absolute, so the code package is limited to 1024 MB of memory (and a soft-guarantee reservation of the same). 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.Code packages (containers or processes) are not able to allocate more memory than this limit, and attempting to do so results in an out-of-memory exception. 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.For resource limit enforcement to work, all code packages within a service package should have memory limits specified.

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

Distribuire l'applicazione del contenitoreDeploy the container application

Salvare tutte le modifiche e compilare l'applicazione.Save all your changes and build the application. Per pubblicare l'applicazione, fare clic con il pulsante destro del mouse su MyFirstContainer in Esplora soluzioni e scegliere Pubblica.To publish your application, right-click on MyFirstContainer in Solution Explorer and select Publish.

In Endpoint connessione immettere l'endpoint di gestione per il cluster,In Connection Endpoint, enter the management endpoint for the cluster. ad esempio "containercluster.westus2.cloudapp.azure.com:19000".For example, "containercluster.westus2.cloudapp.azure.com:19000". L'endpoint di connessione del client è disponibile nel pannello Panoramica per il cluster nel portale di Azure.You can find the client connection endpoint in the Overview blade for your cluster in the Azure portal.

Fare clic su Pubblica.Click Publish.

Service Fabric Explorer è uno strumento basato sul Web che permette di analizzare e gestire applicazioni e nodi in un cluster di Service Fabric.Service Fabric Explorer is a web-based tool for inspecting and managing applications and nodes in a Service Fabric cluster. Aprire un browser Web e passare a http://containercluster.westus2.cloudapp.azure.com:19080/Explorer/ per seguire la distribuzione dell'applicazione.Open a browser and navigate to http://containercluster.westus2.cloudapp.azure.com:19080/Explorer/ and follow the application deployment. L'applicazione viene distribuita, ma rimane in stato di errore fino a quando l'immagine non viene scaricata nei nodi del cluster. L'operazione può richiedere del tempo, a seconda delle dimensioni dell'immagine: ErroreThe application deploys but is in an error state until the image is downloaded on the cluster nodes (which can take some time, depending on the image size): Error

L'applicazione è pronta quando è in stato Ready: ProntoThe application is ready when it's in Ready state: Ready

Aprire un browser Web e passare a http://containercluster.westus2.cloudapp.azure.com:8081.Open a browser and navigate to http://containercluster.westus2.cloudapp.azure.com:8081. Verrà visualizzata l'intestazione "Hello World!"You should see the heading "Hello World!" nel browser.display in the browser.

Eseguire la puliziaClean up

Mentre il cluster è in esecuzione, continuano a essere addebitati i relativi costi. È quindi consigliabile eliminare il cluster.You continue to incur charges while the cluster is running, consider deleting your cluster. I party cluster vengono eliminati automaticamente dopo alcune ore.Party clusters are automatically deleted after a few hours.

Dopo aver effettuato il push dell'immagine nel registro contenitori, è possibile eliminare l'immagine locale dal computer di sviluppo:After you push the image to the container registry you can delete the local image from your development computer:

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

Manifesti di esempio completi del servizio e dell'applicazione di Service FabricComplete example Service Fabric application and service manifests

Di seguito sono riportati i manifesti completi del servizio e dell'applicazione usati in questo articolo.Here are the complete service and application manifests used in this article.

ServiceManifest.xmlServiceManifest.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="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://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>
      </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 directoy 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.xmlApplicationManifest.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="http://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="http://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 contenitoreConfigure time interval before container is force terminated

È 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).You can configure a time interval for the runtime to wait before the container is removed after the service deletion (or a move to another node) has started. Configurando l'intervallo di tempo, viene inviato il comando docker stop <time in seconds> al contenitore.Configuring the time interval sends the docker stop <time in seconds> command to the container. Per altri dettagli, vedere docker stop.For more detail, see docker stop. L'intervallo di tempo per l'attesa viene specificato nella sezione Hosting.The time interval to wait is specified under the Hosting section. Il frammento di manifesto del cluster seguente illustra come impostare l'intervallo di attesa:The following cluster manifest snippet shows how to set the wait interval:

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

L'intervallo di tempo predefinito è impostato su 10 secondi.The default time interval is set to 10 seconds. Poiché questa configurazione è dinamica, un aggiornamento della sola configurazione nel cluster aggiorna il timeout.Since this configuration is dynamic, a config only upgrade on the cluster updates the timeout.

Configurare il runtime per rimuovere le immagini del contenitore non usateConfigure the runtime to remove unused container images

È possibile configurate il cluster di Service Fabric per rimuovere le immagini del contenitore non usate dal nodo.You can configure the Service Fabric cluster to remove unused container images from the node. Questa configurazione consente di riacquisire spazio su disco se nel nodo sono presenti troppe immagini del contenitore.This configuration allows disk space to be recaptured if too many container images are present on the node. Per abilitare questa funzionalità, aggiornare la sezione Hosting nel manifesto del cluster, come illustrato nel frammento seguente:To enable this feature, update the Hosting section in the cluster manifest as shown in the following snippet:

{
        "name": "Hosting",
        "parameters": [
          {
            "PruneContainerImages": “True”,
            "ContainerImagesToSkip": "microsoft/windowsservercore|microsoft/nanoserver|…",
          ...
          }
        ]
} 

Le immagini che non devono essere eliminate possono essere specificate nel parametro ContainerImagesToSkip.For images that should not be deleted, you can specify them under the ContainerImagesToSkip parameter.

Passaggi successiviNext steps