Partilhar via


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

Gorjeta

Este conteúdo é um trecho do eBook, .NET Microservices Architecture for Containerized .NET Applications, disponível no .NET Docs ou como um PDF para download gratuito que pode ser lido offline.

Miniatura da capa do eBook .NET Microservices Architecture for Containerized .NET Applications.

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 com 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 vai criar suas imagens personalizadas do Docker. (As 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ê pode implantar toda a solução em uma única ação orquestrada pelo comando docker-compose up CLI ou pode implantá-la de forma transparente a partir do Visual Studio. Caso contrário, você precisaria 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 compilação. Outras teclas são opcionais e são análogas às suas docker run contrapartes 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. Este código não é o arquivo docker-compose real do eShopOnContainers. Em vez disso, é uma versão simplificada e consolidada em um único arquivo, o que não é a melhor maneira de trabalhar com arquivos docker-compose, como será explicado mais adiante.

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 é services. Sob essa chave, você define os serviços que deseja implantar e executar quando executa o comando ou quando implanta a docker-compose up partir 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 Description
WebMVC Contêiner incluindo o aplicativo MVC ASP.NET Core consumindo os microsserviços do lado do servidor C#
catalog-api Contêiner, incluindo o microsserviço Catalog ASP.NET Core Web API
api de encomenda Contêiner, incluindo o microsserviço Ordering ASP.NET Core Web API
SQLDATA Contêiner executando o SQL Server para Linux, contendo os bancos de dados de microsserviços
cesta-api Contêiner com o microsserviço Basket ASP.NET Core Web API
cesta de dados Contêiner executando o serviço de cache REDIS, com o banco de dados da cesta como um cache REDIS

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

Com foco em um único contêiner, o catalog-api container-microservice 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

Este serviço em contentores tem a seguinte configuração básica:

  • Baseia-se na imagem personalizada eshop/catalog-api . Por uma questão de simplicidade, não há nenhuma configuração de chave build: no arquivo. Isso significa que a imagem deve ter sido construída anteriormente (com o docker build) 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á contendo vários bancos de dados. Portanto, você precisa de menos memória em sua máquina 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. Isto é conveniente; ser capaz de usar essa resolução de nomes (interna ao host do Docker) resolverá o endereço de rede para que você não precise saber o IP interno para os contêineres que 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 ao implantar na produção nos hosts finais ou fazendo isso a partir de seus pipelines de CI/CD nos Serviços de DevOps do Azure ou no seu sistema de DevOps preferido.

  • Ele expõe a porta 80 para acesso interno ao serviço catalog-api dentro do host Docker. O host é atualmente uma VM Linux porque é baseado 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 na máquina host do Docker (a VM Linux).

  • Ele vincula o serviço Web ao serviço sqldata (a instância do SQL Server para 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 aspeto é importante porque catalog-api precisa ter o banco de dados do SQL Server instalado e funcionando primeiro. No entanto, esse tipo de dependência de contêiner não é suficiente em muitos casos, porque o Docker verifica apenas no nível do contêiner. Às vezes, o serviço (neste caso, o SQL Server) ainda pode não estar pronto, por isso é aconselhável implementar a lógica de repetição com backoff 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 externos ou máquinas fora do host do Docker (ou seja, fora da VM Linux padrão, que é um host Docker de desenvolvimento), como uma instância local do SQL Server em seu PC 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 seguintes cenários principais.

Ambientes de desenvolvimento

Quando você desenvolve aplicativos, é importante ser capaz de executar um aplicativo em um ambiente de desenvolvimento isolado. Você pode usar o comando docker-compose CLI para criar esse ambiente ou o Visual Studio, que usa docker-compose sob as capas.

O arquivo docker-compose.yml permite configurar e documentar todas as dependências de serviço do seu aplicativo (outros serviços, cache, bancos de dados, filas, etc.). Usando o comando docker-compose CLI, 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 Docker, mas também servem como arquivos de documentação convenientes sobre a composição do seu aplicativo de vários contêineres.

Ambientes de teste

Uma parte importante de qualquer processo de implantação contínua (CD) ou integração contínua (CI) são os testes de unidade e os 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 muito 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 Compose para implantar em um mecanismo de Docker remoto. 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 definições de configuração de instalação e metadados como as do docker-compose.yml, mas no formato exigido pelo outro orquestrador.

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

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

Ao segmentar ambientes diferentes, você deve usar vários arquivos de composição. 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 das aplicações.

Por padrão, Compose lê dois arquivos, um docker-compose.yml e um arquivo docker-compose.override.yml opcional. Como 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 de docker-compose.vs.debug.g.yml adicional para depurar o aplicativo, você pode examinar esse arquivo na pasta obj\Docker\ na pasta principal da solução.

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

Figura 6-11. arquivos docker-compose no Visual Studio 2019

Estrutura do arquivo de 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 próprio nome sugere, contém definições de configuração que substituem a configuração base, como a 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, mas específicas para um ambiente ou para uma implantação.

Segmentação em vários ambientes

Um caso de uso típico é quando você define vários arquivos de composição para que possa direcionar vários ambientes, como produção, preparação, CI ou desenvolvimento. Para dar suporte a essas diferenças, você pode dividir sua configuração de composição em vários arquivos, como mostra a 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 de docker-compose.yml base

Você pode combinar vários arquivos docker-compose*.yml para lidar com diferentes ambientes. Você começa com o arquivo docker-compose.yml base. Este arquivo base contém as definições de configuração base ou estática que não mudam dependendo do ambiente. Por exemplo, o aplicativo eShopOnContainers tem o seguinte arquivo docker-compose.yml (simplificado com menos serviços) como 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 de serviço webmvc, por exemplo, poderá ver como essas informações são praticamente as mesmas, independentemente do ambiente que você possa estar segmentando. Você tem as seguintes informações:

  • O nome do serviço: webmvc.

  • Imagem personalizada do recipiente: eshop/webmvc.

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

  • Dependências em outros serviços, portanto, esse contêiner não é iniciado até que os outros contêineres de dependência tenham iniciado.

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 preparação, você deve colocar a configuração que é específica para cada ambiente.

Normalmente, o docker-compose.override.yml é usado para seu ambiente de desenvolvimento, como no exemplo a seguir do 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 ao 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 a partir do Visual Studio), o comando lê as substituições automaticamente como se estivesse mesclando ambos os arquivos.

Suponha que você queira outro arquivo de composição para o ambiente de produção, com diferentes valores de configuração, portas ou cadeias de conexão. Você pode criar outro arquivo de substituição, como um 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. Compose 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, ser capaz de obter informações de configuração de variáveis de ambiente, como mostramos em exemplos anteriores. Você pode fazer referência a 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 fazer referência ao 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 maneiras diferentes, dependendo do seu ambiente host (Linux, Windows, cluster de nuvem, etc.). No entanto, uma abordagem conveniente é usar um arquivo .env. Os arquivos docker-compose suportam a 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 (sistema operacional host ou variáveis de ambiente do cluster). Você coloca esse arquivo .env na pasta a partir 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

Criação de imagens otimizadas do ASP.NET Core Docker

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 fonte 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. Os 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 é construído para que o processo de instanciação seja mais rápido. Quando o contêiner é iniciado, ele deve estar pronto para ser executado. Não restaure e compile em tempo de execução usando os comandos e dotnet build CLI, dotnet restore como você pode ver em postagens de 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êiner. O .NET não é apenas uma estrutura leve com um pequeno espaço de memória; a equipe se concentrou em imagens otimizadas do Docker para três cenários principais e as publicou no registro do Docker Hub em dotnet/, começando com a versão 2.1:

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

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

  • SDK: para cenários de desenvolvimento e construção
  • ASPNET: Para cenários de produção ASP.NET
  • tempo de execução: para cenários de produção .NET
  • runtime-deps: para cenários de produção de aplicativos autônomos

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

Recursos adicionais