Criar a sua primeira aplicação de contentor do Service Fabric no Windows

Para executar uma aplicação existente num contentor do Windows num cluster do Service Fabric, não precisa de fazer quaisquer alterações à sua aplicação. Este artigo orienta você na criação de uma imagem do Docker contendo um aplicativo Web Python Flask e na implantação em um cluster do Azure Service Fabric. Também vai partilhar a sua aplicação contentorizada através do Azure Container Registry. Este artigo pressupõe uma compreensão básica do Docker. Para saber mais sobre o Docker, leia a Descrição Geral do Docker.

Nota

Este artigo aplica-se a um ambiente de desenvolvimento do Windows. O tempo de execução do cluster do Service Fabric e o tempo de execução do Docker devem estar em execução no mesmo sistema operacional. Não é possível executar contêineres do Windows em um cluster Linux.

Nota

Recomendamos que utilize o módulo do Azure Az PowerShell para interagir com o Azure. Veja Instalar o Azure PowerShell para começar. Para saber como migrar para o módulo do Az PowerShell, veja Migrar o Azure PowerShell do AzureRM para o Az.

Pré-requisitos

  • Um computador de programação com:

  • Um cluster do Windows com três ou mais nós em execução no Windows Server com contêineres.

    Para este artigo, a versão (compilação) do Windows Server com contêineres em execução nos nós do cluster deve corresponder à versão da máquina de desenvolvimento. Isso ocorre porque você cria a imagem do docker em sua máquina de desenvolvimento e há restrições de compatibilidade entre as versões do sistema operacional contêiner e o sistema operacional host no qual ele é implantado. Para obter mais informações, consulte Compatibilidade do sistema operacional host e do sistema operacional host do Windows Server.

    Para determinar a versão do Windows Server com Contêineres necessária para o cluster, execute o ver comando em um prompt de comando do Windows na máquina de desenvolvimento. Consulte a compatibilidade do sistema operacional host e do sistema operacional host do Windows Server antes de criar um cluster.

  • Um registo no Azure Container Registry - Criar um registo de contentor na sua subscrição do Azure.

Nota

Há suporte para a implantação de contêineres em um cluster do Service Fabric em execução no Windows 10. Consulte este artigo para obter informações sobre como configurar o Windows 10 para executar contêineres do Windows.

Nota

As versões 6.2 e posteriores do Service Fabric oferecem suporte à implantação de contêineres em clusters executados no Windows Server versão 1709.

Definir o contentor do Docker

Crie uma imagem com base na imagem de Python que se encontra no Docker Hub.

Especifique o contentor do Docker num Dockerfile. O Dockerfile consiste em instruções para configurar o ambiente no interior do contentor, para carregar a aplicação que pretende executar e para mapear as portas. O Dockerfile é a entrada para o comando docker build, o que cria a imagem.

Crie um diretório vazio e crie o ficheiro Dockerfile (sem extensão de ficheiro). Adicione o seguinte ao Dockerfile e guarde as alterações:

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

Leia a referência do Dockerfile para obter mais informações.

Criar uma aplicação Web básica

Crie uma aplicação web Flask que escute na porta 80 e que devolva Hello World!. No mesmo diretório, crie o ficheiro requirements.txt. Adicione o seguinte e guarde as alterações:

Flask

Crie também o ficheiro app.py e adicione o seguinte fragmento de código:

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)

Faça login no Docker e construa a imagem

Em seguida, criaremos a imagem que executa seu aplicativo Web. Ao extrair imagens públicas do Docker (como python:2.7-windowsservercore em nosso Dockerfile), é uma prática recomendada autenticar com sua conta do Docker Hub em vez de fazer uma solicitação pull anônima.

Nota

Ao fazer solicitações pull anônimas frequentes, você pode ver erros do Docker semelhantes ou ERROR: toomanyrequests: Too Many Requests.You have reached your pull rate limit. Autenticar no Docker Hub para evitar esses erros. Consulte Gerenciar conteúdo público com o Registro de Contêiner do Azure para obter mais informações.

Abra uma janela do PowerShell e navegue para o diretório que contém o Dockerfile. Em seguida, execute os seguintes comandos:

docker login
docker build -t helloworldapp .

Este comando cria a nova imagem através das instruções fornecidas no seu Dockerfile e dá à imagem o nome (identificação -t) helloworldapp. Para criar uma imagem de contentor, a imagem de base começa por ser transferida do Hub do Docker ao qual aplicação está adicionada.

Quando o comando de criação concluir, execute o comando docker images para ver informações sobre a nova imagem:

$ docker images

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

Executar a aplicação localmente

Verifique a sua imagem localmente antes de a enviar para o registo de contentor.

Execute a aplicação:

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

nome dá um nome ao contentor em execução (em vez do ID do contentor).

Assim que o contentor for iniciado, localize o respetivo endereço IP para que possa ligar-se ao seu contentor em execução a partir de um browser:

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

Se esse comando não retornar nada, execute o seguinte comando e inspecione o elemento NetworkSettings-Networks> para o endereço IP:

docker inspect my-web-site

Ligue-se ao contentor em execução. Abra um navegador da Web apontando para o endereço IP retornado, por exemplo "http://172.31.194.61". Você deve ver o título "Olá Mundo!" exibido no navegador.

Para parar o contentor, execute:

docker stop my-web-site

Elimine o contentor do seu computador de programação:

docker rm my-web-site

Enviar a imagem para o registo de contentor

Depois de confirmar que o contentor é executado no seu computador de programação, envie a imagem para o seu registo no Azure Container Registry.

Execute docker login para entrar no registro de contêiner com suas credenciais de registro.

O exemplo a seguir passa a ID e a senha de uma entidade de serviço do Microsoft Entra. Por exemplo, poderá ter atribuído um principal de serviço ao seu registo no âmbito de um cenário de automatização. Ou, você pode entrar usando seu nome de usuário e senha do registro.

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

O comando seguinte cria uma etiqueta, ou alias, da imagem, com um caminho completamente qualificado para o seu registo. Este exemplo coloca a imagem no espaço de nomes samples para evitar sobrepovoar a raiz do registo.

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

Envie a imagem para o seu registo de contentor:

docker push myregistry.azurecr.io/samples/helloworldapp

Criar o serviço do contentor no Visual Studio

O SDK e as ferramentas do Service Fabric fornecem um modelo de serviço para o ajudar a criar uma aplicação de contentor.

  1. Inicie o Visual Studio. Selecione Ficheiro>Novo>Projeto.
  2. Selecione Aplicação do Service Fabric, dê-lhe o nome "MyFirstContainer" e clique em OK.
  3. Selecione Contentor na lista de modelos de serviço.
  4. Em Nome da Imagem, introduza "myregistry.azurecr.io/samples/helloworldapp", a imagem que enviou para o repositório do seu contentor.
  5. Dê um nome ao serviço e clique em OK.

Configurar a comunicação

O serviço de contentor precisa de um ponto final para comunicação. Adicione um elemento Endpoint com o protocolo, a porta e o tipo ao ficheiro ServiceManifest.xml. Neste exemplo, é utilizada uma porta fixa 8081. Se não especificar uma porta, é escolhida uma porta aleatória do intervalo de portas da aplicação.

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

Nota

Pontos de extremidade adicionais para um serviço podem ser adicionados declarando elementos EndPoint adicionais com valores de propriedade aplicáveis. Cada porta só pode declarar um valor de protocolo.

Ao definir um ponto final, o Service Fabric publica o ponto final no serviço de Nomes. Este contentor pode ser resolvido por outros serviços em execução no cluster. Também pode realizar comunicação de contentor para contentor através do proxy inverso. Para realizar a comunicação, forneça a porta de escuta HTTP do proxy inverso e o nome dos serviços com os quais quer comunicar como variáveis de ambiente.

O serviço está a escutar uma porta específica (8081 neste exemplo). Quando implementa a aplicação num cluster do Azure, tanto o cluster como a aplicação são executados atrás de um balanceador de carga do Azure. A porta da aplicação tem de ser aberta no balanceador de carga do Azure para que o tráfego de entrada possa chegar ao serviço. Pode abrir esta porta no balanceador de carga do Azure com um script do PowerShell ou no portal do Azure.

Configurar e definir variáveis de ambiente

Pode especificar as variáveis de ambiente para cada pacote do código no manifesto do serviço. Esta funcionalidade está disponível para todos os serviços, independentemente de estarem implementados como contentores ou processos ou como executáveis convidados. Pode substituir os valores das variáveis de ambiente no manifesto de aplicação ou especificá-los durante a implementação como parâmetros de aplicação.

O seguinte fragmento XML do manifesto do serviço mostra um exemplo de como especificar variáveis de ambiente para um pacote do código:

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

Estas variáveis de ambiente podem ser substituídas no manifesto de aplicação:

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

Configurar o mapeamento de portas porta-a-anfitrião e deteção de contentor para contentor

Configure uma porta de anfitrião utilizada para comunicar com o contentor. O enlace da porta mapeia a porta em que o serviço está a escutar no interior do contentor para uma porta no anfitrião. Adicione um elemento PortBinding no elemento ContainerHostPolicies do ficheiro ApplicationManifest.xml. Neste artigo, ContainerPort é 80 (o contentor expõe a porta 80, conforme especificado no Dockerfile) e EndpointRef é "Guest1TypeEndpoint" (o ponto final definido anteriormente no manifesto do serviço). Os pedidos de entrada para o serviço na porta 8081 são mapeados para a porta 80 no contentor.

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

Nota

PortBindings adicionais para um serviço podem ser adicionados declarando elementos PortBinding adicionais com valores de propriedade aplicáveis.

Configurar autenticação de repositório de contêiner

Consulte Autenticaçãode repositório de contêiner para saber como configurar diferentes tipos de autenticação para download de imagens de contêiner.

Configurar o modo de isolamento

O Windows suporta dois modos de isolamento para contentores: processo e Hyper-V. No modo de isolamento de processo, todos os contentores em execução no mesmo computador anfitrião partilham o kernel com o anfitrião. No modo de isolamento de Hyper-V, os kernels estão isolados entre cada contentor de Hyper-V e o anfitrião do contentor. O modo de isolamento está especificado no elemento ContainerHostPolicies no ficheiro de manifesto de aplicação. Os modos de isolamento que pode especificar são process, hyperv e default. O padrão é o modo de isolamento de processo em hosts do Windows Server. Em hosts Windows 10, apenas o modo de isolamento Hyper-V é suportado, portanto, o contêiner é executado no modo de isolamento Hyper-V, independentemente de sua configuração de modo de isolamento. O fragmento seguinte mostra como o modo de isolamento é especificado no ficheiro de manifesto de aplicação.

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

Nota

O modo de isolamento de Hyper-v está disponível nos SKUs do Azure Ev3 e Dv3, que têm suporte para virtualização aninhada.

Configurar a governação de recursos

A governação de recursos restringe os recursos que o contentor pode utilizar no anfitrião. O elemento ResourceGovernancePolicy, que está especificado no manifesto de aplicação, é utilizado para declarar os limites de recursos para um pacote do código do serviço. Pode definir limites de recursos para os seguintes recursos: Memória, MemorySwap, CpuShares (peso relativo de CPU), MemoryReservationInMB, BlkioWeight (peso relativo de BlockIO). Neste exemplo, o Guest1Pkg do pacote de serviço obtém um núcleo nos nós de cluster onde está colocado. Os limites de memória são absolutos, pelo que o pacote do código está limitado a 1024 MB de memória (e uma reserva de garantia com o mesmo valor). Os pacotes do código (contentores ou processos) não conseguem alocar mais memória para além deste limite. Tentar fazê-lo resulta numa exceção de memória esgotada. Para que a imposição dos limites de recursos funcione, todos os pacotes do código dentro de um pacote de serviço devem ter limites de memória especificados.

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

Configurar docker HEALTHCHECK

A partir da versão v6.1, o Service Fabric integra automaticamente eventos HEALTHCHECK do docker no respetivo relatório de estado de funcionamento do sistema. Isto significa que, se o seu contentor tiver HEALTHCHECK ativado, o Service Fabric comunicará o estado de funcionamento sempre que o estado de funcionamento do contentor for alterado, conforme comunicado pelo Docker. Quando o health_status for bom estado de funcionamento é apresentado no Service Fabric Explorer um relatório com o estado de funcionamento OK e é apresentado AVISO se o health_status for mau estado de funcionamento.

A partir da versão de atualização mais recente da v6.4, você tem a opção de especificar que as avaliações HEALTHCHECK do docker devem ser relatadas como um erro. Se essa opção estiver habilitada, um relatório de integridade OK aparecerá quando health_status estiver íntegro e ERROR aparecerá quando health_status não estiver íntegro.

A instrução HEALTHCHECK que aponta para a verificação atual que é efetuada para monitorizar o estado de funcionamento do contentor tem de estar presente no dockerfile utilizado ao gerar a imagem de contentor.

Screenshot shows details of the Deployed Service Package NodeServicePackage.

HealthCheckUnhealthyApp

HealthCheckUnhealthyDsp

Pode configurar o comportamento de HEALTHCHECK para cada contentor, especificando as opções HealthConfig como parte de ContainerHostPolicies em ApplicationManifest.

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

Por padrão, IncludeDockerHealthStatusInSystemHealthReport está definido como true, RestartContainerOnUnhealthyDockerHealthStatus está definido como false e TreatContainerUnhealthyStatusAsError está definido como false.

Se RestartContainerOnUnhealthyDockerHealthStatus estiver definido como verdadeiro, um contentor que esteja a comunicar repetidamente um mau estado de funcionamento é reiniciado (possivelmente nos outros nós).

Se TreatContainerUnhealthyStatusAsError estiver definido como true, os relatórios de integridade ERROR aparecerão quando o health_status do contêiner não estiver íntegro.

Se pretender desativar a integração de HEALTHCHECK em todo o cluster do Service Fabric, terá de definir EnableDockerHealthCheckIntegration como falso.

Implementar a aplicação de contentor

Guarde todas as alterações e crie a aplicação. Para publicar a sua aplicação, clique com o botão direito do rato em MyFirstContainer, no Explorador de Soluções, e selecione Publicar.

No Ponto Final da Ligação, introduza o ponto final de gestão para o cluster. Por exemplo, containercluster.westus2.cloudapp.azure.com:19000. Pode encontrar o ponto final de ligação do cliente no separador Descrição Geral do seu cluster no portal do Azure.

Clique em Publicar.

O Service Fabric Explorer é uma ferramenta baseada na Web utilizada para inspecionar e gerir aplicações e nós num cluster do Service Fabric. Abra um browser e navegue para http://containercluster.westus2.cloudapp.azure.com:19080/Explorer/ e siga a implementação da aplicação. O aplicativo é implantado, mas está em um estado de erro até que a imagem seja baixada nos nós do cluster (o que pode levar algum tempo, dependendo do tamanho da imagem): Error

O aplicativo estará pronto quando estiver no Ready estado: Ready

Abra um browser e navegue para http://containercluster.westus2.cloudapp.azure.com:8081. Você deve ver o título "Olá Mundo!" exibido no navegador.

Limpeza

Continua a incorrer em custos enquanto o cluster está em execução, pelo que deve considerar eliminar o seu cluster.

Depois de enviar a imagem para o registo de contentor, pode eliminar a imagem local do seu computador de programação:

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

Compatibilidade do sistema operacional host e do sistema operacional host do Windows Server

Os contêineres do Windows Server não são compatíveis em todas as versões de um sistema operacional host. Por exemplo:

  • Os contêineres do Windows Server criados usando o Windows Server versão 1709 não funcionam em um host que executa o Windows Server versão 2016.
  • Os contêineres do Windows Server criados usando o Windows Server 2016 funcionam no modo de isolamento do Hyper-V somente em um host que executa o Windows Server versão 1709.
  • Com os contêineres do Windows Server criados usando o Windows Server 2016, talvez seja necessário garantir que a revisão do sistema operacional do contêiner e do sistema operacional do host sejam os mesmos ao executar no modo de isolamento de processo em um host que executa o Windows Server 2016.

Para saber mais, consulte Compatibilidade de versão de contêiner do Windows.

Considere a compatibilidade do sistema operacional host e do seu sistema operacional de contêiner ao criar e implantar contêineres no cluster do Service Fabric. Por exemplo:

  • Certifique-se de implantar contêineres com um sistema operacional compatível com o sistema operacional nos nós do cluster.
  • Verifique se o modo de isolamento especificado para seu aplicativo de contêiner é consistente com o suporte para o sistema operacional do contêiner no nó em que ele está sendo implantado.
  • Considere como as atualizações do sistema operacional para os nós ou contêineres do cluster podem afetar sua compatibilidade.

Recomendamos as seguintes práticas para garantir que os contêineres sejam implantados corretamente no cluster do Service Fabric:

  • Use a marcação de imagem explícita com suas imagens do Docker para especificar a versão do sistema operacional Windows Server a partir da qual um contêiner é criado.
  • Use a marcação do sistema operacional no arquivo de manifesto do aplicativo para garantir que seu aplicativo seja compatível com diferentes versões e atualizações do Windows Server.

Nota

Com o Service Fabric versão 6.2 e posterior, você pode implantar contêineres baseados no Windows Server 2016 localmente em um host Windows 10. No Windows 10, os contêineres são executados no modo de isolamento do Hyper-V, independentemente do modo de isolamento definido no manifesto do aplicativo. Para saber mais, consulte Configurar o modo de isolamento.

Indicar imagens de contentor específicas da compilação de SO

Os contêineres do Windows Server podem não ser compatíveis entre diferentes versões do sistema operacional. Por exemplo, os contêineres do Windows Server criados usando o Windows Server 2016 não funcionam no Windows Server versão 1709 no modo de isolamento de processo. Assim, se os nós de cluster forem atualizados para a versão mais recente, os serviços de contêiner criados usando as versões anteriores do sistema operacional poderão falhar. Para contornar isso com a versão 6.1 do tempo de execução e mais recente, o Service Fabric oferece suporte à especificação de várias imagens do sistema operacional por contêiner e à marcação delas com as versões de compilação do sistema operacional no manifesto do aplicativo. Você pode obter a versão de compilação do sistema operacional executando winver em um prompt de comando do Windows. Antes de atualizar o SO nos nós, atualize os manifestos da aplicação e especifique a substituições de imagem por versão de SO. O fragmento seguinte mostra como especificar várias imagens de contentor no manifesto da aplicação, 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> 

A versão de compilação para o Windows Server 2016 é 14393 e a versão de compilação para o Windows Server versão 1709 é 16299. O manifesto de serviço continua a especificar apenas uma imagem por serviço de contentores, conforme a imagem abaixo:

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

Nota

As funcionalidades de identificação da versão de compilação do SO só estão disponíveis para o Service Fabric no Windows

Se o SO subjacente na VM for a compilação 16299 (versão 1709), o Service Fabric escolhe a imagem de contentor correspondente a essa versão do Windows Server. Se também for fornecida uma imagem de contentor não identificada juntamente com as imagens de contentor identificadas no manifesto da aplicação, o Service Fabric trata-a como uma imagem que funciona em todas as versões. Identificar as imagens de contentor explicitamente para evitar problemas durante as atualizações.

A imagem de contentor não marcada irá funcionar como uma substituição da imagem que fornece o ServiceManifest. Portanto, a imagem "myregistry.azurecr.io/samples/helloworldappDefault" irá substituir o ImageName "myregistry.azurecr.io/samples/helloworldapp" no ServiceManifest.

Exemplo completo da aplicação do Service Fabric e dos manifestos do serviço

Seguem-se os manifestos completos do serviço e da aplicação utilizados neste artigo.

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>

Configurar o intervalo de tempo antes do contentor ser forçado a terminar

Pode configurar um intervalo de tempo para o tempo de execução para aguardar antes do contentor ser removido após a eliminação do serviço (ou uma mudança para outro nó) ser iniciada. Configurar o intervalo de tempo envia o comando docker stop <time in seconds> para o contentor. Para obter mais detalhes, veja paragem do docker. O intervalo de tempo de espera é especificado na secção Hosting. A Hosting seção pode ser adicionada na criação do cluster ou posteriormente em uma atualização de configuração. O fragmento do manifesto do cluster seguinte mostra como definir o intervalo de espera:

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

O intervalo de tempo predefinido está definido para 10 segundos. Uma vez que esta configuração é dinâmica, uma configuração apenas de atualização no cluster atualiza tempo limite.

Configurar o tempo de execução para remover as imagens do contentor não utilizadas

Pode configurar o cluster do Service Fabric para remover as imagens do contentor não utilizadas do nó. Esta configuração permite que o espaço em disco seja recapturado se existirem demasiadas imagens do contentor no nó. Para habilitar esse recurso, atualize a seção Hospedagem no manifesto do cluster, conforme mostrado no seguinte trecho:

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

Para imagens que não devem ser eliminadas, pode especificá-las no parâmetro ContainerImagesToSkip.

Configurar o tempo de transferência de imagem de contentor

O tempo de execução do Service Fabric aloca 20 minutos para transferir e extrair imagens de contentor, que funciona para a maioria das imagens de contentor. Para imagens de grandes dimensões ou quando a ligação de rede for lenta, poderá ser necessário aumentar o tempo de espera antes de abortar a transferência e extração de imagens. Este limite de tempo é definido utilizando o atributo ContainerImageDownloadTimeout na secção Alojamento do manifesto do cluster, conforme mostrado no seguinte fragmento:

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

Definir a política de retenção de contentores

Para ajudar a diagnosticar falhas no arranque de contentores, o Service Fabric (versão 6.1 ou superior) suporta a retenção de contentores que terminaram ou cujo arranque falhou. Esta política pode ser definida no ficheiro ApplicationManifest.xml, conforme mostrado no fragmento seguinte:

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

A definição ContainersRetentionCount especifica o número de contentores que vão ser retidos quando falham. Se não for especificado um valor negativo, todos os contentores com falhas serão mantidos. Se o atributo ContainersRetentionCount não for especificado, não serão retidos contentores. O atributo ContainersRetentionCount também suporta Parâmetros de Aplicação, para que os utilizadores possam especificar valores diferentes para clusters de teste e produção. Utilize restrições de posicionamento para segmentar o serviço de contentores para um nó particular ao utilizar esta funcionalidade para impedir a passagem do serviço de contentores para outros nós. Quaisquer contentores retidos que utilizem esta funcionalidade têm de ser removidos manualmente.

Iniciar o daemon do Docker com argumentos personalizados

Com a versão e posterior 6.2 do runtime do Service Fabric, pode iniciar o daemon do Docker com argumentos personalizados. Quando os argumentos personalizados são especificados, o Service Fabric não passa outros argumentos ao motor do docker, exceto o argumento --pidfile. Por conseguinte, --pidfile não deve ser passado como argumento. Além disso, o argumento deve continuar a ter o daemon do docker a escutar o pipe de nome predefinido no Windows (ou o socket de domínio unix no Linux) para o Service Fabric comunicar com o Daemon. Os argumentos personalizados passam pelo manifesto do cluster na secção Alojamento, em ContainerServiceArguments como mostrado no seguinte fragmento:

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

Substituição de ponto de entrada

Com a versão 8.2 do ServiceFabric Runtime, o ponto de entrada para contêiner e pacote de código de host exe pode ser substituído. Isso pode ser usado nos casos em que todos os elementos de manifesto permanecem os mesmos, mas a imagem do contêiner precisa ser alterada, em seguida, o provisionamento de uma versão de tipo de aplicativo diferente não é mais necessário, ou argumentos diferentes precisam ser passados com base no cenário de teste ou prod e o ponto de entrada permanece o mesmo.

A seguir está um exemplo de como substituir o ponto de entrada do contêiner:

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>

Depois que as substituições no manifesto do aplicativo forem especificadas, o contêiner com o nome da imagem myregistry.azurecr.io/samples/helloworldapp, comandos de comandoOverride, source sourceOverride e entryPoint entryPointOverride serão iniciados.

Da mesma forma, abaixo está um exemplo sobre como substituir o 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

A substituição do ponto de entrada não é suportada para SetupEntryPoint.

Próximos passos