Contentorizar uma aplicação .NET com dotnet publish

Os contêineres têm muitos recursos e benefícios, como ser uma infraestrutura imutável, fornecer uma arquitetura portátil e permitir escalabilidade. A imagem pode ser usada para criar contêineres para seu ambiente de desenvolvimento local, nuvem privada ou nuvem pública. Neste tutorial, você aprenderá como colocar em contêineres um aplicativo .NET usando o comando dotnet publishing .

Pré-requisitos

Instale os seguintes pré-requisitos:

Além desses pré-requisitos, é recomendável que você esteja familiarizado com os Serviços do Trabalhador no .NET.

Criar aplicação .NET

Você precisa de um aplicativo .NET para criar contêineres, então comece criando um novo aplicativo a partir de um modelo. Abra o terminal, crie uma pasta de trabalho (diretório de exemplo), se ainda não o fez, e altere os diretórios para que você esteja nele. Na pasta de trabalho, execute o seguinte comando para criar um novo projeto em um subdiretório chamado Worker:

dotnet new worker -o Worker -n DotNet.ContainerImage

Sua árvore de pastas tem a seguinte aparência:

📁 sample-directory
    └──📂 Worker
        ├──appsettings.Development.json
        ├──appsettings.json
        ├──DotNet.ContainerImage.csproj
        ├──Program.cs
        ├──Worker.cs
        └──📂 obj
            ├── DotNet.ContainerImage.csproj.nuget.dgspec.json
            ├── DotNet.ContainerImage.csproj.nuget.g.props
            ├── DotNet.ContainerImage.csproj.nuget.g.targets
            ├── project.assets.json
            └── project.nuget.cache

O dotnet new comando cria uma nova pasta chamada Worker e gera um serviço de trabalho que, quando executado, registra uma mensagem a cada segundo. Na sessão do terminal, altere os diretórios e navegue até a pasta Trabalhador . Use o comando para iniciar o dotnet run aplicativo.

dotnet run
Building...
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:00 -05:00
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\Worker
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:01 -05:00
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:02 -05:00
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:03 -05:00
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
Attempting to cancel the build...

O modelo de trabalho é executado indefinidamente. Use o comando cancelar Ctrl+C para pará-lo.

Adicionar pacote NuGet

O pacote NuGet Microsoft.NET.Build.Containers é atualmente necessário para publicar projetos não Web como um contêiner. Para adicionar o pacote NuGet ao modelo de trabalho, execute o Microsoft.NET.Build.Containers seguinte comando dotnet add package :

dotnet add package Microsoft.NET.Build.Containers

Gorjeta

Se você estiver criando um aplicativo Web e usando o .NET SDK 7.0.300 ou posterior, o pacote não será necessário — o SDK contém a mesma funcionalidade pronta para uso.

Definir o nome da imagem do contêiner

Há várias opções de configuração disponíveis ao publicar um aplicativo como um contêiner.

Por padrão, o nome da imagem do contêiner é o AssemblyName do projeto. Se esse nome for inválido como um nome de imagem de contêiner, você poderá substituí-lo especificando um ContainerRepository conforme mostrado no seguinte arquivo de projeto:

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
    <ContainerRepository>dotnet-worker-image</ContainerRepository>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
  </ItemGroup>
</Project>

Para obter mais informações, consulte ContainerRepository.

Por padrão, o nome da imagem do contêiner é o AssemblyName do projeto. Se esse nome for inválido como um nome de imagem de contêiner, você poderá substituí-lo especificando um (ContainerImageName obsoleto) ou o preferido ContainerRepository , conforme mostrado no seguinte arquivo de projeto:

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
    <ContainerImageName>dotnet-worker-image</ContainerImageName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
    <PackageReference Include="Microsoft.NET.Build.Containers" Version="7.0.401" />
  </ItemGroup>
</Project>

Para obter mais informações, consulte ContainerImageName.

Publicar aplicativo .NET

Para publicar o aplicativo .NET como um contêiner, use o seguinte comando dotnet publishing :

dotnet publish --os linux --arch x64 /t:PublishContainer -c Release

O comando anterior da CLI do .NET publica o aplicativo como um contêiner:

  • Visando o Linux como o sistema operacional (--os linux).
  • Especificando uma arquitetura x64 (--arch x64).
  • Usando a configuração de liberação (-c Release).

Importante

Para criar o contêiner localmente, você deve ter o daemon do Docker em execução. Se ele não estiver em execução quando você tentar publicar o aplicativo como um contêiner, ocorrerá um erro semelhante ao seguinte:

..\build\Microsoft.NET.Build.Containers.targets(66,9): error MSB4018:
   The "CreateNewImage" task failed unexpectedly. [..\Worker\DotNet.ContainerImage.csproj]

Gorjeta

Dependendo do tipo de aplicativo que você está fazendo contêineres, as opções de linha de comando (opções) podem variar. Por exemplo, o /t:PublishContainer argumento só é necessário para aplicativos .NET não Web, como console modelos e modelos worker . Para modelos da Web, substitua o /t:PublishContainer argumento por -p:PublishProfile=DefaultContainer. Para obter mais informações, consulte Compilações de contêiner do SDK do .NET, edição #141.

O comando produz uma saída semelhante à saída de exemplo:

Determining projects to restore...
  All projects are up-to-date for restore.
  DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\DotNet.ContainerImage.dll
  DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\publish\
  Building image 'dotnet-worker-image' with tags latest on top of base image mcr.microsoft.com/dotnet/aspnet:8.0
  Pushed container 'dotnet-worker-image:latest' to Docker daemon
Determining projects to restore...
  All projects are up-to-date for restore.
  DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\DotNet.ContainerImage.dll
  DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\publish\
  Building image 'dotnet-worker-image' with tags 1.0.0 on top of base image mcr.microsoft.com/dotnet/aspnet:7.0
  Pushed container 'dotnet-worker-image:1.0.0' to Docker daemon

Este comando compila seu aplicativo de trabalho para a pasta de publicação e envia o contêiner para o registro do docker local.

Configurar imagem de contêiner

Você pode controlar muitos aspetos do contêiner gerado por meio das propriedades do MSBuild. Em geral, se você pode usar um comando em um Dockerfile para definir alguma configuração, você pode fazer o mesmo via MSBuild.

Nota

As únicas exceções são RUN os comandos. Devido à forma como os contêineres são construídos, eles não podem ser emulados. Se precisar dessa funcionalidade, você precisará usar um Dockerfile para criar suas imagens de contêiner.

ContainerArchiveOutputPath

A partir do .NET 8, você pode criar um contêiner diretamente como um arquivo tar.gz . Esse recurso é útil se o fluxo de trabalho não for simples e exigir que você, por exemplo, execute uma ferramenta de digitalização sobre suas imagens antes de enviá-las. Depois que o arquivo é criado, você pode movê-lo, digitalizá-lo ou carregá-lo em uma cadeia de ferramentas local do Docker.

Para publicar em um arquivo, adicione a ContainerArchiveOutputPath propriedade ao comando dotnet publish , por exemplo:

dotnet publish \
  -p PublishProfile=DefaultContainer \
  -p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz

Você pode especificar um nome de pasta ou um caminho com um nome de arquivo específico. Se você especificar o nome da pasta, o nome do arquivo gerado para o arquivo de imagem será $(ContainerRepository).tar.gz. Esses arquivos podem conter várias tags dentro deles, apenas como um único arquivo é criado para todos ContainerImageTags.

Configuração de nomenclatura de imagem de contêiner

As imagens de contêiner seguem uma convenção de nomenclatura específica. O nome da imagem é composto por várias partes, o registro, porta opcional, repositório e tag opcional e família.

REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]

Por exemplo, considere o nome da imagem totalmente qualificada mcr.microsoft.com/dotnet/runtime:8.0-alpine :

  • mcr.microsoft.com é o registro (e, neste caso, representa o registro de contêiner da Microsoft).
  • dotnet/runtime é o repositório (mas alguns consideram isso o user/repository).
  • 8.0-alpine é a tag e a família (a família é um especificador opcional que ajuda a desambiguar o empacotamento do sistema operacional).

Algumas propriedades descritas nas seções a seguir correspondem ao gerenciamento de partes do nome da imagem gerada. Considere a tabela a seguir que mapeia a relação entre o nome da imagem e as propriedades de compilação:

Parte do nome da imagem Propriedade MSBuild Valores de exemplo
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerRepository dotnet/runtime
TAG ContainerImageTag 8.0
FAMILY ContainerFamily -alpine
Parte do nome da imagem Propriedade MSBuild Valores de exemplo
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerImageName dotnet/runtime
TAG ContainerImageTag 8.0

As seções a seguir descrevem as várias propriedades que podem ser usadas para controlar a imagem de contêiner gerada.

ContainerBaseImage

A propriedade container base image controla a imagem usada como base para sua imagem. Por padrão, os seguintes valores são inferidos com base nas propriedades do seu projeto:

  • Se o seu projeto for independente, a mcr.microsoft.com/dotnet/runtime-deps imagem será usada como imagem base.
  • Se o seu projeto for um projeto ASP.NET Core, a mcr.microsoft.com/dotnet/aspnet imagem será usada como imagem base.
  • Caso contrário, a mcr.microsoft.com/dotnet/runtime imagem é usada como a imagem base.

A tag da imagem é inferida como sendo o componente numérico do seu escolhido TargetFramework. Por exemplo, um projeto direcionado net6.0 resulta na 6.0 tag da imagem base inferida, e um net7.0-linux projeto usa a 7.0 tag e assim por diante.

Se você definir um valor aqui, deverá definir o nome totalmente qualificado da imagem para usar como base, incluindo qualquer tag de sua preferência:

<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>
<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:7.0</ContainerBaseImage>
</PropertyGroup>

ContainerFamily

A partir do .NET 8, você pode usar a propriedade MSBuild para escolher uma família diferente de imagens de contêiner fornecidas pela Microsoft como a ContainerFamily imagem base para seu aplicativo. Quando definido, esse valor é anexado ao final da tag específica do TFM selecionada, alterando a tag fornecida. Por exemplo, para usar as variantes do Alpine Linux das imagens base do .NET, você pode definir ContainerFamily como alpine:

<PropertyGroup>
    <ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>

A configuração do projeto anterior resulta em uma marca final de para um aplicativo de destino .NET 8.8.0-alpine

Este campo é de forma livre e muitas vezes pode ser usado para selecionar diferentes distribuições do sistema operacional, configurações de pacote padrão ou qualquer outro tipo de alterações em uma imagem base. Este campo é ignorado quando ContainerBaseImage é definido. Para obter mais informações, consulte Imagens de contêiner .NET.

ContainerRuntimeIdentifier

A propriedade container runtime identifier controla o sistema operacional e a arquitetura usados pelo contêiner se o ContainerBaseImage oferecer suporte a mais de uma plataforma. Por exemplo, a mcr.microsoft.com/dotnet/runtime imagem atualmente suporta linux-x64, e win10-x64 imagens todas atrás da mesma tag, linux-armlinux-arm64 então as ferramentas precisam de uma maneira de ser informado qual dessas versões você pretende usar. Por padrão, isso é definido como o valor do RuntimeIdentifier que você escolheu quando publicou o contêiner. Essa propriedade raramente precisa ser definida explicitamente - em vez disso, use a -r opção para o dotnet publish comando. Se a imagem que você escolheu não suportar a que você escolheu, resultará em um erro que descreve os RuntimeIdentifiers que a RuntimeIdentifier imagem suporta.

Você sempre pode definir a propriedade para um nome de imagem totalmente qualificado, incluindo a ContainerBaseImage tag , para evitar a necessidade de usar essa propriedade.

<PropertyGroup>
    <ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>

Para obter mais informações sobre os identificadores de tempo de execução suportados pelo .NET, consulte Catálogo RID.

ContainerRegistry

A propriedade do registro de contêiner controla o registro de destino, o local para o qual a imagem recém-criada será enviada. Por padrão, ele é enviado por push para o daemon Docker local, mas você também pode especificar um registro remoto. Ao usar um registro remoto que requer autenticação, você autentica usando os mecanismos conhecidos docker login . Para obter mais informações, consulte a autenticação em registros de contêiner para obter mais detalhes. Para obter um exemplo concreto de uso dessa propriedade, considere o seguinte exemplo XML:

<PropertyGroup>
    <ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>

Essa ferramenta oferece suporte à publicação em qualquer registro que ofereça suporte à API HTTP V2 do Registro do Docker. Isto inclui os seguintes registos explicitamente (e provavelmente muitos mais implicitamente):

Para obter notas sobre como trabalhar com estes registos, consulte as notas específicas do registo.

ContainerRepository

O repositório de contêiner é o nome da própria imagem, por exemplo, dotnet/runtime ou my-app. Por padrão, o AssemblyName do projeto é usado.

<PropertyGroup>
    <ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>

ContainerImageName

O nome da imagem do contêiner controla o nome da própria imagem, por exemplo, dotnet/runtime ou my-app. Por padrão, o AssemblyName do projeto é usado.

<PropertyGroup>
    <ContainerImageName>my-app</ContainerImageName>
</PropertyGroup>

Nota

A partir do .NET 8, ContainerImageName foi preterido em favor do ContainerRepository.

Os nomes das imagens consistem em um ou mais segmentos delimitados por barras, cada um dos quais só pode conter caracteres alfanuméricos minúsculos, pontos, sublinhados e traços, e devem começar com uma letra ou número. Quaisquer outros caracteres resultam em um erro sendo lançado.

ContainerImageTag(s)

A propriedade container image tag controla as tags geradas para a imagem. Para especificar uma única tag use e para várias tags use ContainerImageTagContainerImageTags.

Importante

Ao usar ContainerImageTagso , você acabará com várias imagens, uma por tag exclusiva.

As tags geralmente são usadas para se referir a diferentes versões de um aplicativo, mas também podem se referir a diferentes distribuições do sistema operacional ou até mesmo configurações diferentes.

A partir do .NET 8, quando uma tag não é fornecida, o padrão é latest.

Por padrão, o do projeto é usado como o Version valor da tag.

Para substituir o padrão, especifique uma das seguintes opções:

<PropertyGroup>
    <ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>

Para especificar várias tags, use um conjunto de tags delimitado por ponto-e-vírgula ContainerImageTags na propriedade, semelhante à configuração de várias TargetFrameworks:

<PropertyGroup>
    <ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>

As tags só podem conter até 127 caracteres alfanuméricos, pontos, sublinhados e traços. Devem começar com um caractere alfanumérico ou um sublinhado. Qualquer outro formulário resulta em um erro sendo lançado.

Nota

Ao usar ContainerImageTagso , as tags são delimitadas por um ; caractere. Se você estiver chamando dotnet publish a partir da linha de comando (como é o caso com a maioria dos ambientes de CI/CD), você precisará envolver os valores em um wrap único ' e interno com aspas duplas ", por exemplo (='"tag-1;tag-2"'). Considere o seguinte dotnet publish comando:

dotnet publish -p ContainerImageTags='"1.2.3-alpha2;latest"'

Isso resulta em duas imagens sendo geradas: my-app:1.2.3-alpha2 e my-app:latest.

Gorjeta

Se você tiver problemas com a ContainerImageTags propriedade, considere definir o escopo de uma variável ContainerImageTags de ambiente:

ContainerImageTags='1.2.3;latest' dotnet publish

ContainerLabel

O rótulo do contêiner adiciona um rótulo de metadados ao contêiner. Os rótulos não têm impacto no contêiner em tempo de execução, mas geralmente são usados para armazenar metadados de versão e criação para uso por scanners de segurança e outras ferramentas de infraestrutura. Você pode especificar qualquer número de rótulos de contêiner.

O ContainerLabel nó tem dois atributos:

  • Include: A chave do rótulo.
  • Value: O valor do rótulo (pode estar vazio).
<ItemGroup>
    <ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>

Para obter uma lista de rótulos criados por padrão, consulte rótulos de contêiner padrão.

Configurar a execução de contêiner

Para controlar a execução do contêiner, você pode usar as seguintes propriedades do MSBuild.

ContainerWorkingDirectory

O nó do diretório de trabalho do contêiner controla o diretório de trabalho do contêiner, o diretório no qual os comandos são executados se nenhum outro comando for executado.

Por padrão, o valor do diretório é usado como o /app diretório de trabalho.

<PropertyGroup>
    <ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>

ContainerPort

A porta do contêiner adiciona portas TCP ou UDP à lista de portas conhecidas para o contêiner. Isso permite que tempos de execução de contêineres, como o Docker, mapeiem essas portas para a máquina host automaticamente. Isso geralmente é usado como documentação para o contêiner, mas também pode ser usado para habilitar o mapeamento automático de portas.

O ContainerPort nó tem dois atributos:

  • Include: O número da porta a ser exposta.
  • Type: O padrão é tcp, os valores válidos são ou udptcp .
<ItemGroup>
    <ContainerPort Include="80" Type="tcp" />
</ItemGroup>

A partir do .NET 8, o ContainerPort é inferido quando não é fornecido explicitamente com base em várias variáveis de ambiente ASP.NET bem conhecidas:

  • ASPNETCORE_URLS
  • ASPNETCORE_HTTP_PORTS
  • ASPNETCORE_HTTPS_PORTS

Se essas variáveis de ambiente estiverem presentes, seus valores serão analisados e convertidos em mapeamentos de porta TCP. Essas variáveis de ambiente são lidas da imagem base, se presente, ou das variáveis de ambiente definidas em seu projeto por meio ContainerEnvironmentVariable de itens. Para obter mais informações, consulte ContainerEnvironmentVariable.

ContainerEnvironmentVariable

O nó da variável de ambiente do contêiner permite adicionar variáveis de ambiente ao contêiner. As variáveis de ambiente são acessíveis ao aplicativo em execução no contêiner imediatamente e geralmente são usadas para alterar o comportamento em tempo de execução do aplicativo em execução.

O ContainerEnvironmentVariable nó tem dois atributos:

  • Include: O nome da variável de ambiente.
  • Value: O valor da variável de ambiente.
<ItemGroup>
  <ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>

Para obter mais informações, consulte Variáveis de ambiente .NET.

Configurar comandos de contêiner

Por padrão, as ferramentas de contêiner iniciam seu aplicativo usando o binário AppHost gerado para seu aplicativo (se seu aplicativo usa um AppHost) ou o dotnet comando mais a DLL do seu aplicativo.

No entanto, você pode controlar como seu aplicativo é executado usando alguma combinação de ContainerAppCommand, , ContainerDefaultArgsContainerAppCommandArgse ContainerAppCommandInstruction.

Esses diferentes pontos de configuração existem porque diferentes imagens de base usam combinações diferentes do contêiner ENTRYPOINT e das propriedades, e COMMAND você deseja ser capaz de suportar todos eles. Os padrões devem ser utilizáveis para a maioria dos aplicativos, mas se você quiser personalizar o comportamento de inicialização do aplicativo, deve:

  • Identifique o binário a ser executado e defina-o como ContainerAppCommand
  • Identifique quais argumentos são necessários para que seu aplicativo seja executado e defina-os como ContainerAppCommandArgs
  • Identifique quais argumentos (se houver) são opcionais e podem ser substituídos por um usuário e defina-os como ContainerDefaultArgs
  • Defina ContainerAppCommandInstruction como DefaultArgs

Para obter mais informações, consulte os seguintes itens de configuração.

ContainerAppCommand

O item de configuração do comando do aplicativo é o ponto de entrada lógico do seu aplicativo. Para a maioria dos aplicativos, este é o AppHost, o binário executável gerado para seu aplicativo. Se o seu aplicativo não gerar um AppHost, esse comando normalmente será dotnet <your project dll>. Esses valores são aplicados depois de qualquer ENTRYPOINT um em seu contêiner base, ou diretamente se nenhum ENTRYPOINT for definido.

A ContainerAppCommand configuração tem uma única Include propriedade, que representa o comando, opção ou argumento a ser usado no comando entrypoint:

<ItemGroup Label="ContainerAppCommand Assignment">
  <!-- This is how you would start the dotnet ef tool in your container -->
  <ContainerAppCommand Include="dotnet" />
  <ContainerAppCommand Include="ef" />

  <!-- This shorthand syntax means the same thing, note the semicolon separating the tokens. -->
  <ContainerAppCommand Include="dotnet;ef" />
</ItemGroup>

ContainerAppCommandArgs

Este item de configuração do comando do aplicativo args representa todos os argumentos logicamente necessários para seu aplicativo que devem ser aplicados ao ContainerAppCommand. Por padrão, nenhum é gerado para um aplicativo. Quando presentes, os args são aplicados ao seu contêiner quando ele é executado.

A ContainerAppCommandArgs configuração tem uma única Include propriedade, que representa a opção ou argumento a ser aplicado ao ContainerAppCommand comando.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above, 
       this would be the way to force the database to update.
  -->
  <ContainerAppCommandArgs Include="database" />
  <ContainerAppCommandArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerAppCommandArgs Include="database;update" />
</ItemGroup>

ContainerDefaultArgs

Este item de configuração args padrão representa quaisquer argumentos substituíveis pelo usuário para seu aplicativo. Essa é uma boa maneira de fornecer padrões que seu aplicativo pode precisar executar de uma forma que facilite a inicialização, mas ainda assim fácil de personalizar.

A ContainerDefaultArgs configuração tem uma única Include propriedade, que representa a opção ou argumento a ser aplicado ao ContainerAppCommand comando.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above, 
       this would be the way to force the database to update.
  -->
  <ContainerDefaultArgs Include="database" />
  <ContainerDefaultArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerDefaultArgs Include="database;update" />
</ItemGroup>

ContainerAppCommandInstruction

A configuração de instruções de comando do aplicativo ajuda a controlar a maneira como o , , ContainerAppCommand, ContainerAppCommandArgsContainerEntrypointArgse ContainerDefaultArgs são combinados para formar o ContainerEntrypointcomando final que é executado no contêiner. Isso depende muito se um ENTRYPOINT está presente na imagem base. Esta propriedade usa um dos três valores: "DefaultArgs", , "Entrypoint"ou "None".

  • Entrypoint:
    • Neste modo, o ponto de entrada é definido por ContainerAppCommand, ContainerAppCommandArgse ContainerDefaultArgs.
  • None:
    • Neste modo, o ponto de entrada é definido por ContainerEntrypoint, ContainerEntrypointArgse ContainerDefaultArgs.
  • DefaultArgs:
    • Este é o modo mais complexo — se nenhum dos ContainerEntrypoint[Args] itens estiver presente, o e será usado para criar o ponto de entrada e ContainerDefaultArgs o ContainerAppCommand[Args] comando. O ponto de entrada da imagem base para imagens base que a codificam ou /usr/bin/dotnet são ignoradas para dotnet que você tenha controle total.
    • Se ambos ContainerEntrypoint estiverem ContainerAppCommand presentes, então ContainerEntrypoint torna-se o ponto de entrada e ContainerAppCommand torna-se o comando.

Nota

Os ContainerEntrypoint itens e ContainerEntrypointArgs configuração foram preteridos a partir do .NET 8.

Importante

Isso é para usuários avançados - a maioria dos aplicativos não precisa personalizar seu ponto de entrada nesse grau. Para obter mais informações e se você quiser fornecer casos de uso para seus cenários, consulte GitHub: discussões sobre compilações de contêiner do .NET SDK.

ContainerUser

A propriedade de configuração do usuário controla o usuário padrão no qual o contêiner é executado. Isso geralmente é usado para executar o contêiner como um usuário não raiz, o que é uma prática recomendada para segurança. Há algumas restrições para essa configuração estar ciente:

  • Ele pode assumir várias formas: nome de usuário, IDs de usuário do linux, nome do grupo, ID do grupo do linux e outras variantes de ID username:groupname.
  • Não há nenhuma verificação de que o usuário ou grupo especificado existe na imagem.
  • Alterar o usuário pode alterar o comportamento do aplicativo, especialmente em relação a coisas como permissões do sistema de arquivos.

O valor padrão deste campo varia de acordo com o TFM do projeto e o sistema operacional de destino:

  • Se você estiver direcionando o .NET 8 ou superior e usando as imagens de tempo de execução da Microsoft, então:
    • no Linux o usuário sem raiz é usado (embora seja referenciado por seu ID de usuário app )
    • no Windows o usuário ContainerUser sem raiz é usado
  • Caso contrário, nenhum padrão ContainerUser será usado
<PropertyGroup>
  <ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>

Gorjeta

A APP_UID variável de ambiente é usada para definir informações do usuário em seu contêiner. Esse valor pode vir de variáveis de ambiente definidas em sua imagem base (como as imagens do Microsoft .NET) ou você mesmo pode defini-lo por meio da ContainerEnvironmentVariable sintaxe.

No entanto, você pode controlar como seu aplicativo é executado usando ContainerEntrypoint e ContainerEntrypointArgs.

ContainerEntrypoint

O ponto de entrada do contêiner pode ser usado para personalizar o ENTRYPOINT do contêiner, que é o executável que é chamado quando o contêiner é iniciado. Por padrão, para compilações que criam um host de aplicativo, ele é definido como o ContainerEntrypoint. Para compilações que não criam um executável, o é usado como o dotnet path/to/app.dllContainerEntrypoint.

O ContainerEntrypoint nó tem um único atributo:

  • Include: O comando, opção ou argumento a ser usado no ContainerEntrypoint comando.

Por exemplo, considere o seguinte grupo de itens de projeto .NET de exemplo:

<ItemGroup Label="Entrypoint Assignment">
  <!-- This is how you would start the dotnet ef tool in your container -->
  <ContainerEntrypoint Include="dotnet" />
  <ContainerEntrypoint Include="ef" />

  <!-- This shorthand syntax means the same thing.
       Note the semicolon separating the tokens. -->
  <ContainerEntrypoint Include="dotnet;ef" />
</ItemGroup>

ContainerEntrypointArgs

O nó args do ponto de entrada do contêiner controla os argumentos padrão fornecidos ao ContainerEntrypoint. Isso deve ser usado quando o é um programa que o ContainerEntrypoint usuário pode querer usar por conta própria. Por padrão, não ContainerEntrypointArgs são criados em seu nome.

O ContainerEntrypointArg nó tem um único atributo:

  • Include: A opção ou argumento a ser aplicado ao ContainerEntrypoint comando.

Considere o seguinte exemplo de grupo de itens de projeto .NET:

<ItemGroup>
  <!-- Assuming the ContainerEntrypoint defined above,
       this would be the way to update the database by
       default, but let the user run a different EF command. -->
  <ContainerEntrypointArgs Include="database" />
  <ContainerEntrypointArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerEntrypointArgs Include="database;update" />
</ItemGroup>

Rótulos de contêiner padrão

Os rótulos são frequentemente usados para fornecer metadados consistentes em imagens de contêiner. Este pacote fornece alguns rótulos padrão para incentivar uma melhor manutenção das imagens geradas.

  • org.opencontainers.image.created está definido para o formato ISO 8601 do UTC DateTimeatual.

Para obter mais informações, consulte Implementar rótulos convencionais sobre a infraestrutura de rótulos existente.

Clean up resources (Limpar recursos)

Neste artigo, você publicou um trabalhador .NET como uma imagem de contêiner. Se desejar, exclua este recurso. Use o docker images comando para ver uma lista de imagens instaladas.

docker images

Considere o seguinte exemplo de saída:

REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
dotnet-worker-image   1.0.0     25aeb97a2e21   12 seconds ago   191MB

Gorjeta

Os arquivos de imagem podem ser grandes. Normalmente, você removeria contêineres temporários criados durante o teste e o desenvolvimento do aplicativo. Você geralmente mantém as imagens base com o tempo de execução instalado se planeja criar outras imagens com base nesse tempo de execução.

Para excluir a imagem, copie o ID da imagem e execute o docker image rm comando:

docker image rm 25aeb97a2e21

Próximos passos