Compartilhar via


Definindo seu aplicativo de vários contêineres com docker-compose.yml

Dica

Esse conteúdo é um trecho do eBook, arquitetura de microsserviços do .NET para aplicativos .NET em contêineres, disponível em do .NET Docs ou como um PDF para download gratuito que pode ser lido offline.

miniatura da capa do eBook sobre arquitetura de microsserviços do .NET para aplicativos .NET em contêineres.

Neste guia, o arquivo docker-compose.yml foi introduzido na seção Etapa 4. Defina seus serviços em docker-compose.yml ao criar um aplicativo Docker de vários contêineres. No entanto, há maneiras adicionais de usar os arquivos docker-compose que vale a pena explorar em mais detalhes.

Por exemplo, você pode descrever explicitamente como deseja implantar seu aplicativo de vários contêineres no arquivo docker-compose.yml. Opcionalmente, você também pode descrever como criar suas imagens personalizadas do Docker. (Imagens personalizadas do Docker também podem ser criadas com a CLI do Docker.)

Basicamente, você define cada um dos contêineres que deseja implantar, além de determinadas características para cada implantação de contêiner. Depois de ter um arquivo de descrição de implantação de vários contêineres, você poderá implantar toda a solução em uma única ação orquestrada pelo comando docker-compose up CLI ou implantá-la de forma transparente no Visual Studio. Caso contrário, você precisará usar a CLI do Docker para implantar contêiner por contêiner em várias etapas usando o docker run comando da linha de comando. Portanto, cada serviço definido em docker-compose.yml deve especificar exatamente uma imagem ou construção. Outras teclas são opcionais e são análogas aos seus docker run equivalentes de linha de comando.

O código YAML a seguir é a definição de um possível arquivo de docker-compose.yml global, mas único, para o exemplo eShopOnContainers. Esse código não é o arquivo docker-compose real do eShopOnContainers. Em vez disso, é uma versão simplificada e consolidada em um único arquivo, que não é a melhor maneira de trabalhar com arquivos docker-compose, como será explicado posteriormente.

version: '3.4'

services:
  webmvc:
    image: eshop/webmvc
    environment:
      - CatalogUrl=http://catalog-api
      - OrderingUrl=http://ordering-api
      - BasketUrl=http://basket-api
    ports:
      - "5100:80"
    depends_on:
      - catalog-api
      - ordering-api
      - basket-api

  catalog-api:
    image: eshop/catalog-api
    environment:
      - ConnectionString=Server=sqldata;Initial Catalog=CatalogData;User Id=sa;Password=[PLACEHOLDER]
    expose:
      - "80"
    ports:
      - "5101:80"
    #extra hosts can be used for standalone SQL Server or services at the dev PC
    extra_hosts:
      - "CESARDLSURFBOOK:10.0.75.1"
    depends_on:
      - sqldata

  ordering-api:
    image: eshop/ordering-api
    environment:
      - ConnectionString=Server=sqldata;Database=Services.OrderingDb;User Id=sa;Password=[PLACEHOLDER]
    ports:
      - "5102:80"
    #extra hosts can be used for standalone SQL Server or services at the dev PC
    extra_hosts:
      - "CESARDLSURFBOOK:10.0.75.1"
    depends_on:
      - sqldata

  basket-api:
    image: eshop/basket-api
    environment:
      - ConnectionString=sqldata
    ports:
      - "5103:80"
    depends_on:
      - sqldata

  sqldata:
    environment:
      - SA_PASSWORD=[PLACEHOLDER]
      - ACCEPT_EULA=Y
    ports:
      - "5434:1433"

  basketdata:
    image: redis

A chave raiz neste arquivo são os serviços. Nessa chave, você define os serviços que deseja implantar e executar quando executa o docker-compose up comando ou quando implanta do Visual Studio usando esse arquivo docker-compose.yml. Nesse caso, o arquivo docker-compose.yml tem vários serviços definidos, conforme descrito na tabela a seguir.

Nome do serviço Descrição
webmvc Contêiner incluindo o aplicativo ASP.NET Core MVC que consome os microsserviços em C# no lado do servidor
catalog-api Contêiner incluindo o microsserviço da API Web do Catalog ASP.NET Core
ordering-api Contêiner, incluindo o microsserviço de API Web do ASP.NET Core de Pedidos
sqldata Contêiner executando o SQL Server para Linux, mantendo os bancos de dados de microsserviços
basket-api Contêiner com o microsserviço de API Web do ASP.NET Core de Cesta
basketdata Contêiner executando o serviço de cache REDIS, com o banco de dados de cesta como um cache REDIS

Um contêiner de API de Serviço Web simples

Com foco em um único contêiner, o microsserviço de contêiner catalog-api tem uma definição simples.

  catalog-api:
    image: eshop/catalog-api
    environment:
      - ConnectionString=Server=sqldata;Initial Catalog=CatalogData;User Id=sa;Password=[PLACEHOLDER]
    expose:
      - "80"
    ports:
      - "5101:80"
    #extra hosts can be used for standalone SQL Server or services at the dev PC
    extra_hosts:
      - "CESARDLSURFBOOK:10.0.75.1"
    depends_on:
      - sqldata

Esse serviço em contêineres tem a seguinte configuração básica:

  • Ele é baseado na imagem personalizada de eshop/catalog-api . Por questões de simplicidade, não há compilação: configuração de chave no arquivo. Isso significa que a imagem deve ter sido criada anteriormente (com o build do Docker) ou ter sido baixada (com o comando docker pull) de qualquer registro do Docker.

  • Ele define uma variável de ambiente chamada ConnectionString com a cadeia de conexão a ser usada pelo Entity Framework para acessar a instância do SQL Server que contém o modelo de dados do catálogo. Nesse caso, o mesmo contêiner do SQL Server está mantendo vários bancos de dados. Portanto, você precisa de menos memória em seu computador de desenvolvimento para o Docker. No entanto, você também pode implantar um contêiner do SQL Server para cada banco de dados de microsserviço.

  • O nome do SQL Server é sqldata, que é o mesmo nome usado para o contêiner que está executando a instância do SQL Server para Linux. Isso é conveniente; ser capaz de usar essa resolução de nomes (interna para o host do Docker) resolverá o endereço de rede para que você não precise saber o IP interno para os contêineres que você está acessando de outros contêineres.

Como a cadeia de conexão é definida por uma variável de ambiente, você pode definir essa variável por meio de um mecanismo diferente e em um momento diferente. Por exemplo, você pode definir uma cadeia de conexão diferente durante a implantação em produção nos hosts finais ou fazer isso através dos pipelines de CI/CD no Azure DevOps Services ou no sistema de DevOps de sua preferência.

  • Ele expõe a porta 80 para acesso interno ao serviço catalog-api dentro do host do Docker. No momento, o host é uma VM do Linux porque se baseia em uma imagem do Docker para Linux, mas você pode configurar o contêiner para ser executado em uma imagem do Windows.

  • Ele encaminha a porta 80 exposta no contêiner para a porta 5101 no computador host do Docker (a VM do Linux).

  • Ele vincula o serviço Web ao serviço sqldata (a instância do SQL Server para o banco de dados Linux em execução em um contêiner). Quando você especificar essa dependência, o contêiner catalog-api não será iniciado até que o contêiner sqldata já tenha sido iniciado; esse aspecto é importante porque a API de catálogo precisa ter o banco de dados do SQL Server em funcionamento primeiro. No entanto, esse tipo de dependência de contêiner não é suficiente em muitos casos, pois o Docker verifica apenas no nível do contêiner. Às vezes, o serviço (nesse caso, o SQL Server) ainda pode não estar pronto, portanto, é aconselhável implementar a lógica de repetição com retirada exponencial nos microsserviços do cliente. Dessa forma, se um contêiner de dependência não estiver pronto por um curto período de tempo, o aplicativo ainda será resiliente.

  • Ele é configurado para permitir o acesso a servidores externos: a configuração extra_hosts permite que você acesse servidores ou computadores externos fora do host do Docker (ou seja, fora da VM padrão do Linux, que é um host do Docker de desenvolvimento), como uma instância local do SQL Server em seu computador de desenvolvimento.

Há também outras configurações mais avançadas docker-compose.yml que discutiremos nas seções a seguir.

Usando arquivos docker-compose para direcionar vários ambientes

Os docker-compose.*.yml arquivos são arquivos de definição e podem ser usados por várias infraestruturas que entendem esse formato. A ferramenta mais simples é o comando docker-compose.

Portanto, usando o comando docker-compose, você pode direcionar os cenários principais a seguir.

Ambientes de desenvolvimento

Ao desenvolver aplicativos, é importante ser capaz de executar um aplicativo em um ambiente de desenvolvimento isolado. Você pode usar o comando docker-compose na linha de comando para criar esse ambiente ou o Visual Studio, que usa docker-compose nos bastidores.

O arquivo docker-compose.yml permite configurar e documentar todas as dependências de serviço do aplicativo (outros serviços, cache, bancos de dados, filas etc.). Usando o comando da CLI do docker-compose, você pode criar e iniciar um ou mais contêineres para cada dependência com um único comando (docker-compose up).

Os arquivos docker-compose.yml são arquivos de configuração interpretados pelo mecanismo do Docker, mas também servem como arquivos de documentação convenientes sobre a composição do aplicativo de vários contêineres.

Ambientes de teste

Uma parte importante de qualquer processo de CD (implantação contínua) ou CI (integração contínua) são os testes de unidade e testes de integração. Esses testes automatizados exigem um ambiente isolado para que não sejam afetados pelos usuários ou qualquer outra alteração nos dados do aplicativo.

Com o Docker Compose, você pode criar e destruir esse ambiente isolado facilmente em alguns comandos do prompt de comando ou scripts, como os seguintes comandos:

docker-compose -f docker-compose.yml -f docker-compose-test.override.yml up -d
./run_unit_tests
docker-compose -f docker-compose.yml -f docker-compose-test.override.yml down

Implantações de produção

Você também pode usar o Compose para implantar em um Mecanismo remoto do Docker. Um caso típico é implantar em uma única instância de host do Docker.

Se você estiver usando qualquer outro orquestrador (por exemplo, Azure Service Fabric ou Kubernetes), talvez seja necessário adicionar configurações de configuração de instalação e metadados, como aquelas em docker-compose.yml, mas no formato exigido pelo outro orquestrador.

De qualquer forma, o docker-compose é uma ferramenta conveniente e um formato de metadados para fluxos de trabalho de desenvolvimento, teste e produção, embora o fluxo de trabalho de produção possa variar no orquestrador que você está usando.

Usando vários arquivos docker-compose para lidar com vários ambientes

Ao destinar-se a ambientes diferentes, você deve usar vários arquivos compose. Essa abordagem permite criar várias variantes de configuração dependendo do ambiente.

Substituindo o arquivo base docker-compose

Você pode usar um único arquivo docker-compose.yml como nos exemplos simplificados mostrados nas seções anteriores. No entanto, isso não é recomendado para a maioria dos aplicativos.

Por padrão, o Compose lê dois arquivos, um docker-compose.yml e um arquivo de docker-compose.override.yml opcional. Conforme mostrado na Figura 6-11, quando você estiver usando o Visual Studio e habilitando o suporte ao Docker, o Visual Studio também cria um arquivo docker-compose.vs.debug.g.yml adicional para depurar o aplicativo, você pode dar uma olhada nesse arquivo na pasta obj\Docker\ na pasta principal da solução.

Arquivos em um projeto de composição do Docker.

Figura 6-11. Arquivos de docker-compose no Visual Studio 2019

Estrutura de arquivos do projeto docker-compose:

  • .dockerignore - usado para ignorar arquivos
  • docker-compose.yml – usado para compor microsserviços
  • docker-compose.override.yml – usado para configurar o ambiente de microsserviços

Você pode editar os arquivos docker-compose com qualquer editor, como Visual Studio Code ou Sublime, e executar o aplicativo com o comando docker-compose up.

Por convenção, o arquivo docker-compose.yml contém sua configuração base e outras configurações estáticas. Isso significa que a configuração do serviço não deve ser alterada dependendo do ambiente de implantação que você está visando.

O arquivo docker-compose.override.yml, como o nome sugere, contém configurações que substituem a configuração base, como configuração que depende do ambiente de implantação. Você também pode ter vários arquivos de substituição com nomes diferentes. Os arquivos de substituição geralmente contêm informações adicionais necessárias para o aplicativo e específicas de um ambiente ou de uma implantação.

Destinando-se a vários ambientes

Um caso de uso típico é quando você define vários arquivos de composição para que você possa direcionar vários ambientes, como produção, preparo, CI ou desenvolvimento. Para dar suporte a essas diferenças, você pode dividir sua configuração de Redação em vários arquivos, conforme mostrado na Figura 6-12.

Diagrama de três arquivos docker-compose definidos para substituir o arquivo base.

Figura 6-12. Vários arquivos docker-compose substituindo valores no arquivo base docker-compose.yml

Você pode combinar vários arquivos docker-compose*.yml para lidar com ambientes diferentes. Você começa com o arquivo de docker-compose.yml base. Esse arquivo base contém as configurações base ou estática que não são alteradas dependendo do ambiente. Por exemplo, o aplicativo eShopOnContainers tem o seguinte arquivo de docker-compose.yml (simplificado com menos serviços) como o arquivo base.

#docker-compose.yml (Base)
version: '3.4'
services:
  basket-api:
    image: eshop/basket-api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Basket/Basket.API/Dockerfile
    depends_on:
      - basketdata
      - identity-api
      - rabbitmq

  catalog-api:
    image: eshop/catalog-api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
    depends_on:
      - sqldata
      - rabbitmq

  marketing-api:
    image: eshop/marketing-api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Marketing/Marketing.API/Dockerfile
    depends_on:
      - sqldata
      - nosqldata
      - identity-api
      - rabbitmq

  webmvc:
    image: eshop/webmvc:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Web/WebMVC/Dockerfile
    depends_on:
      - catalog-api
      - ordering-api
      - identity-api
      - basket-api
      - marketing-api

  sqldata:
    image: mcr.microsoft.com/mssql/server:2019-latest

  nosqldata:
    image: mongo

  basketdata:
    image: redis

  rabbitmq:
    image: rabbitmq:3-management

Os valores no arquivo de docker-compose.yml base não devem ser alterados devido a diferentes ambientes de implantação de destino.

Se você se concentrar na definição do serviço webmvc, por exemplo, poderá ver como essas informações são muito semelhantes, independentemente do ambiente que você esteja visando. Você tem as seguintes informações:

  • O nome do serviço: webmvc.

  • Imagem personalizada do contêiner: eshop/webmvc.

  • O comando para criar a imagem personalizada do Docker, indicando qual Dockerfile usar.

  • Este contêiner depende de outros serviços, portanto, ele não é iniciado até que os contêineres dos quais depende tenham sido iniciados.

Você pode ter uma configuração adicional, mas o ponto importante é que, no arquivo de docker-compose.yml base, você só deseja definir as informações que são comuns entre ambientes. Em seguida, no docker-compose.override.yml ou arquivos semelhantes para produção ou preparo, você deve colocar a configuração específica para cada ambiente.

Normalmente, o docker-compose.override.yml é usado para seu ambiente de desenvolvimento, como no exemplo a seguir de eShopOnContainers:

#docker-compose.override.yml (Extended config for DEVELOPMENT env.)
version: '3.4'

services:
# Simplified number of services here:

  basket-api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basketdata}
      - identityUrl=http://identity-api
      - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
      - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
      - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
      - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
      - AzureServiceBusEnabled=False
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
      - UseLoadTest=${USE_LOADTEST:-False}

    ports:
      - "5103:80"

  catalog-api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sqldata;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=[PLACEHOLDER]}
      - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG_URL:-http://host.docker.internal:5202/api/v1/catalog/items/[0]/pic/}
      - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
      - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
      - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
      - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME}
      - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY}
      - UseCustomizationData=True
      - AzureServiceBusEnabled=False
      - AzureStorageEnabled=False
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
    ports:
      - "5101:80"

  marketing-api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sqldata;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=[PLACEHOLDER]}
      - MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosqldata}
      - MongoDatabase=MarketingDb
      - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
      - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
      - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
      - identityUrl=http://identity-api
      - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
      - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI}
      - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING_URL:-http://host.docker.internal:5110/api/v1/campaigns/[0]/pic/}
      - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME}
      - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY}
      - AzureServiceBusEnabled=False
      - AzureStorageEnabled=False
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
      - UseLoadTest=${USE_LOADTEST:-False}
    ports:
      - "5110:80"

  webmvc:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - PurchaseUrl=http://webshoppingapigw
      - IdentityUrl=http://10.0.75.1:5105
      - MarketingUrl=http://webmarketingapigw
      - CatalogUrlHC=http://catalog-api/hc
      - OrderingUrlHC=http://ordering-api/hc
      - IdentityUrlHC=http://identity-api/hc
      - BasketUrlHC=http://basket-api/hc
      - MarketingUrlHC=http://marketing-api/hc
      - PaymentUrlHC=http://payment-api/hc
      - SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
      - UseCustomizationData=True
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
      - UseLoadTest=${USE_LOADTEST:-False}
    ports:
      - "5100:80"
  sqldata:
    environment:
      - SA_PASSWORD=[PLACEHOLDER]
      - ACCEPT_EULA=Y
    ports:
      - "5433:1433"
  nosqldata:
    ports:
      - "27017:27017"
  basketdata:
    ports:
      - "6379:6379"
  rabbitmq:
    ports:
      - "15672:15672"
      - "5672:5672"

Neste exemplo, a configuração de substituição de desenvolvimento expõe algumas portas para o host, define variáveis de ambiente com URLs de redirecionamento e especifica cadeias de conexão para o ambiente de desenvolvimento. Essas configurações são todas apenas para o ambiente de desenvolvimento.

Quando você executa docker-compose up (ou o inicia no Visual Studio), o comando lerá as substituições automaticamente como se estivesse mesclando os dois arquivos.

Suponha que você queira um outro arquivo Compose para o ambiente de produção, com valores de configuração, portas ou strings de conexão diferentes. Você pode criar outro arquivo de substituição, como o arquivo nomeado docker-compose.prod.yml com diferentes configurações e variáveis de ambiente. Esse arquivo pode ser armazenado em um repositório Git diferente ou gerenciado e protegido por uma equipe diferente.

Como implantar com um arquivo de substituição específico

Para usar vários arquivos de substituição ou um arquivo de substituição com um nome diferente, você pode usar a opção -f com o comando docker-compose e especificar os arquivos. A composição mescla arquivos na ordem em que são especificados na linha de comando. O exemplo a seguir mostra como implantar com arquivos de substituição.

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Usando variáveis de ambiente em arquivos docker-compose

É conveniente, especialmente em ambientes de produção, obter informações de configuração de variáveis de ambiente, como mostramos em exemplos anteriores. Você pode referenciar uma variável de ambiente em seus arquivos docker-compose usando a sintaxe ${MY_VAR}. A linha a seguir de um arquivo docker-compose.prod.yml mostra como referenciar o valor de uma variável de ambiente.

IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105

As variáveis de ambiente são criadas e inicializadas de diferentes maneiras, dependendo do seu ambiente de host (Linux, Windows, cluster de nuvem etc.). No entanto, uma abordagem conveniente é usar um arquivo .env. Os arquivos docker-compose dão suporte à declaração de variáveis de ambiente padrão no arquivo .env. Esses valores para as variáveis de ambiente são os valores padrão. Mas eles podem ser substituídos pelos valores que você pode ter definido em cada um dos seus ambientes (variáveis de sistema operacional do host ou ambiente do cluster). Você coloca esse arquivo .env na pasta da qual o comando docker-compose é executado.

O exemplo a seguir mostra um arquivo .env como o arquivo .env para o aplicativo eShopOnContainers.

# .env file

ESHOP_EXTERNAL_DNS_NAME_OR_IP=host.docker.internal

ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92

O Docker-compose espera que cada linha em um arquivo .env esteja no formato <variable>=<value>.

Os valores definidos no ambiente de tempo de execução sempre substituem os valores definidos dentro do arquivo .env. Da mesma forma, os valores passados por meio de argumentos de linha de comando também substituem os valores padrão definidos no arquivo .env.

Recursos adicionais

Construindo imagens otimizadas do Docker para ASP.NET Core

Se você estiver explorando o Docker e o .NET em fontes na Internet, encontrará Dockerfiles que demonstram a simplicidade de criar uma imagem do Docker copiando sua origem em um contêiner. Esses exemplos sugerem que, usando uma configuração simples, você pode ter uma imagem do Docker com o ambiente empacotado com seu aplicativo. O exemplo a seguir mostra um Dockerfile simples nessa linha.

FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /app
ENV ASPNETCORE_URLS http://+:80
EXPOSE 80
COPY . .
RUN dotnet restore
ENTRYPOINT ["dotnet", "run"]

Um Dockerfile como este funcionará. No entanto, você pode otimizar substancialmente suas imagens, especialmente suas imagens de produção.

No modelo de contêiner e microsserviços, você está constantemente iniciando contêineres. A maneira típica de usar contêineres não reinicia um contêiner adormecido, porque o contêiner é descartável. Orquestradores (como o Kubernetes e o Azure Service Fabric) criam novas instâncias de imagens. O que isso significa é que você precisaria otimizar pré-compilando o aplicativo quando ele for criado para que o processo de instanciação seja mais rápido. Quando o contêiner é iniciado, ele deve estar pronto para executar. Não restaure e compile durante a execução usando os comandos dotnet restore e dotnet build CLI, como você pode encontrar em postagens no blog sobre .NET e Docker.

A equipe do .NET tem feito um trabalho importante para tornar o .NET e o ASP.NET Core uma estrutura otimizada para contêineres. Não só o .NET é uma estrutura leve com um pequeno volume de memória; a equipe se concentrou em imagens otimizadas do Docker para três cenários principais e as publicou no registro do Hub do Docker no dotnet/, começando com a versão 2.1:

  • Desenvolvimento: a prioridade é a capacidade de revisar e depurar rapidamente as modificações, em que o tamanho é secundário.
  • Compilação: a prioridade é compilar o aplicativo e a imagem, e inclui os binários e outras dependências para otimizar os binários.
  • Produção: o foco é a implantação rápida e o início de contêineres, portanto, essas imagens são limitadas aos binários e ao conteúdo necessários para executar o aplicativo.

A equipe do .NET fornece algumas variantes básicas no dotnet/, por exemplo:

  • sdk: para cenários de desenvolvimento e compilação
  • aspnet: para cenários de produção ASP.NET
  • runtime: para cenários de produção do .NET
  • runtime-deps: para cenários de produção de aplicativos autônomos

Para uma inicialização mais rápida, as imagens de runtime também definem automaticamente aspnetcore_urls para a porta 80 e usam o Ngen para criar um cache de imagens nativo de montagens.

Recursos adicionais