Creare la prima applicazione contenitore di Service Fabric in LinuxCreate your first Service Fabric container application on Linux

Per eseguire un'applicazione esistente in un contenitore Linux in un cluster di Service Fabric non è necessario apportare modifiche all'applicazione.Running an existing application in a Linux 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

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-slim

# 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 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 a c:\temp\helloworldapp.Open a PowerShell window and navigate to c:\temp\helloworldapp. 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              86838648aab6        2 minutes ago       194 MB

Eseguire l'applicazione in localeRun the application locally

Verificare l'esecuzione dell'applicazione in contenitore in locale prima di eseguirne il push nel registro contenitori.Verify that your containerized application runs locally before pushing it the container registry.

Eseguire l'applicazione, effettuando il mapping della porta 4000 del computer alla porta 80 esposta dal contenitore:Run the application, mapping your computer's port 4000 to the container's exposed port 80:

docker run -d -p 4000:80 --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).

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

Hello World!

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 dell'applicazione in Docker, eseguire il push dell'immagine nel registro all'interno di Registro contenitori di Azure.After you verify that the application runs in Docker, 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 pacchetto dell'immagine Docker con YeomanPackage the Docker image with Yeoman

Service Fabric SDK per Linux include un generatore Yeoman che semplifica la creazione dell'applicazione e l'aggiunta di un'immagine contenitore.The Service Fabric SDK for Linux includes a Yeoman generator that makes it easy to create your application and add a container image. È possibile usare Yeoman per creare un'applicazione con un singolo contenitore Docker denominato SimpleContainerApp.Let's use Yeoman to create an application with a single Docker container called SimpleContainerApp.

Per creare un'applicazione contenitore di Service Fabric, aprire una finestra del terminale ed eseguire yo azuresfcontainer.To create a Service Fabric container application, open a terminal window and run yo azuresfcontainer.

Assegnare un nome all'applicazione (ad esempio, "mycontainer") e al servizio dell'applicazione (ad esempio, "myservice").Name your application (for example, "mycontainer") and name the application service (for example, "myservice").

Per il nome dell'immagine, specificare l'URL dell'immagine del contenitore in un registro contenitori, ad esempio "myregistry.azurecr.io/samples/helloworldapp".For the image name, provide the URL for the container image in a container registry (for example, "myregistry.azurecr.io/samples/helloworldapp").

Dato che per l'immagine è stato definito un punto di ingresso del carico di lavoro, non è necessario specificare in modo esplicito i comandi di input, che vengono eseguiti all'interno del contenitore in modo che la relativa esecuzione continui dopo l'avvio.Since this image has a workload entry-point defined, you don't need to explicitly specify input commands (commands run inside the container, which will keep the container running after startup).

Specificare "1" come numero di istanze.Specify an instance count of "1".

Generatore Yeoman di Service Fabric per i contenitori

Configurare il mapping delle porte e l'autenticazione per il repository del contenitoreConfigure port mapping and container repository authentication

Il servizio in contenitore richiede un endpoint per la comunicazione.Your containerized service needs an endpoint for communication. Aggiungere ora il protocollo, la porta e il tipo a un Endpoint nel file ServiceManifest.xml sotto il tag 'Resources'.Now add the protocol, port, and type to an Endpoint in the ServiceManifest.xml file under the 'Resources' tag. Per questo articolo, il servizio in contenitore è in ascolto sulla porta 4000:For this article, the containerized service listens on port 4000:


<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="myServiceTypeEndpoint" UriScheme="http" Port="4000" Protocol="http"/>
    </Endpoints>
  </Resources>

Se si specifica UriScheme, l'endpoint del contenitore viene registrato automaticamente con Service Fabric Naming Service per l'individuazione.Providing the UriScheme automatically registers the container endpoint with the Service Fabric Naming service for discoverability. Alla fine di questo articolo viene fornito un file di esempio completo di ServiceManifest.xml.A full ServiceManifest.xml example file is provided at the end of this article.

Configurare il mapping tra la porta del contenitore e la porta dell'host specificando i criteri PortBinding in ContainerHostPolicies nel file ApplicationManifest.xml.Configure the container port-to-host port mapping by specifying a PortBinding policy in ContainerHostPolicies of the ApplicationManifest.xml file. Per questo articolo, il valore di ContainerPort è 80, dato che il contenitore espone la porta 80, come specificato nel Dockerfile, e il valore di EndpointRef è "myServiceTypeEndpoint", ossia l'endpoint definito nel manifesto del servizio.For this article, ContainerPort is 80 (the container exposes port 80, as specified in the Dockerfile) and EndpointRef is "myServiceTypeEndpoint" (the endpoint defined in the service manifest). Per le richieste in ingresso per il servizio sulla porta 4000 viene eseguito il mapping alla porta 80 del contenitore.Incoming requests to the service on port 4000 are mapped to port 80 on the container. Se il contenitore deve eseguire l'autenticazione con un repository privato, aggiungere RepositoryCredentials.If your container needs to authenticate with a private repository, then add RepositoryCredentials. Per questo articolo, aggiungere il nome e la password dell'account per il registro contenitori myregistry.azurecr.io.For this article, add the account name and password for the myregistry.azurecr.io container registry. Verificare che il criterio venga aggiunto sotto il tag 'ServiceManifestImport' corrispondente al pacchetto del servizio corretto.Ensure the policy is added under the 'ServiceManifestImport' tag corresponding to the right service package.

   <ServiceManifestImport>
      <ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
    <Policies>
        <ContainerHostPolicies CodePackageRef="Code">
        <RepositoryCredentials AccountName="myregistry" Password="=P==/==/=8=/=+u4lyOB=+=nWzEeRfF=" PasswordEncrypted="false"/>
        <PortBinding ContainerPort="80" EndpointRef="myServiceTypeEndpoint"/>
        </ContainerHostPolicies>
    </Policies>
   </ServiceManifestImport>

Compilare l'applicazione di Service Fabric e creare il pacchettoBuild and package the Service Fabric application

I modelli Yeoman di Service Fabric includono uno script di compilazione per Gradle, che può essere usato per compilare l'applicazione dal terminale.The Service Fabric Yeoman templates include a build script for Gradle, which you can use to build the application from the terminal. Per compilare l'applicazione e creare il pacchetto, eseguire questo comando:To build and package the application, run the following:

cd mycontainer
gradle

Distribuire l'applicazioneDeploy the application

Dopo aver compilato l'applicazione, è possibile distribuirla nel cluster locale tramite l'interfaccia della riga di comando di Service Fabric.Once the application is built, you can deploy it to the local cluster using the Service Fabric CLI.

Connettersi al cluster locale di Service Fabric.Connect to the local Service Fabric cluster.

sfctl cluster select --endpoint http://localhost:19080

Usare lo script di installazione messo a disposizione nel modello per copiare il pacchetto dell'applicazione nell'archivio immagini del cluster, registrare il tipo di applicazione e creare un'istanza dell'applicazione.Use the install script provided in the template to copy the application package to the cluster's image store, register the application type, and create an instance of the application.

./install.sh

Aprire un browser e passare a Service Fabric Explorer all'indirizzo http://localhost:19080/Explorer. Sostituire localhost con l'indirizzo IP privato della macchina virtuale se si usa Vagrant in Mac OS X.Open a browser and navigate to Service Fabric Explorer at http://localhost:19080/Explorer (replace localhost with the private IP of the VM if using Vagrant on Mac OS X). Espandere il nodo delle applicazioni, nel quale sarà ora presente una voce per il tipo di applicazione e un'altra per la prima istanza del tipo.Expand the Applications node and note that there is now an entry for your application type and another for the first instance of that type.

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

Hello World!

Eseguire la puliziaClean up

Usare lo script di disinstallazione incluso nel modello per eliminare l'istanza dell'applicazione dal cluster di sviluppo locale e annullare la registrazione del tipo di applicazione.Use the uninstall script provided in the template to delete the application instance from the local development cluster and unregister the application type.

./uninstall.sh

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="myservicePkg"
                 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="myserviceType" 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>
        <Commands></Commands>
      </ContainerHost>
    </EntryPoint>
    <!-- Pass environment variables to your container: -->

    <EnvironmentVariables>
      <!--
      <EnvironmentVariable Name="VariableName" Value="VariableValue"/>
      -->
    </EnvironmentVariables>

  </CodePackage>

  <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="myServiceTypeEndpoint" UriScheme="http" Port="4000" Protocol="http"/>
    </Endpoints>
  </Resources>
</ServiceManifest>

ApplicationManifest.xmlApplicationManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="mycontainerType"
                     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">
  <!-- 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="myservicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <RepositoryCredentials AccountName="myregistry" Password="=P==/==/=8=/=+u4lyOB=+=nWzEeRfF=" PasswordEncrypted="false"/>
        <PortBinding ContainerPort="80" EndpointRef="myServiceTypeEndpoint"/>
      </ContainerHostPolicies>
    </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="myservice">
      <!-- On a local development cluster, set InstanceCount to 1.  On a multi-node production 
      cluster, set InstanceCount to -1 for the container service to run on every node in 
      the cluster.
      -->
      <StatelessService ServiceTypeName="myserviceType" InstanceCount="1">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
</ApplicationManifest>

Aggiunta di altri servizi a un'applicazione esistenteAdding more services to an existing application

Per aggiungere un altro servizio contenitore a un'applicazione già creata usando yeoman, seguire questa procedura:To add another container service to an application already created using yeoman, perform the following steps:

  1. Modificare la directory impostandola sulla radice dell'applicazione esistente.Change directory to the root of the existing application. Ad esempio, cd ~/YeomanSamples/MyApplication, se MyApplication è l'applicazione creata da Yeoman.For example, cd ~/YeomanSamples/MyApplication, if MyApplication is the application created by Yeoman.
  2. Eseguire yo azuresfcontainer:AddServiceRun yo azuresfcontainer:AddService

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