Fluxo de trabalho de desenvolvimento para aplicativos Docker
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.
O ciclo de vida de desenvolvimento do aplicativo começa no seu computador, como desenvolvedor, onde você codifica o aplicativo usando seu idioma preferido e o testa localmente. Com esse fluxo de trabalho, não importa qual idioma, estrutura e plataforma você escolha, você está sempre desenvolvendo e testando contêineres do Docker, mas fazendo isso localmente.
Cada contêiner (uma instância de uma imagem do Docker) inclui os seguintes componentes:
- Uma seleção de sistema operacional, por exemplo, uma distribuição Linux, Windows Nano Server ou Windows Server Core.
- Arquivos adicionados durante o desenvolvimento, por exemplo, código-fonte e binários de aplicativos.
- Informações de configuração, como configurações de ambiente e dependências.
Fluxo de trabalho para desenvolver aplicativos baseados em contêiner do Docker
Esta seção descreve o fluxo de trabalho de desenvolvimento de loop interno para aplicativos baseados em contêiner do Docker. O fluxo de trabalho de loop interno significa que ele não está considerando o fluxo de trabalho de DevOps mais amplo, que pode incluir até a implantação de produção, e se concentra apenas no trabalho de desenvolvimento feito no computador do desenvolvedor. As etapas iniciais para configurar o ambiente não estão incluídas, uma vez que essas etapas são feitas apenas uma vez.
Um aplicativo é composto por seus próprios serviços mais bibliotecas adicionais (dependências). A seguir estão as etapas básicas que você geralmente executa ao criar um aplicativo Docker, conforme ilustrado na Figura 5-1.
O processo de desenvolvimento para aplicativos Docker: 1 - Codifique seu aplicativo, 2 - Escreva Dockerfile/s, 3 - Crie imagens definidas em Dockerfile/s, 4 - (opcional) Componha serviços no arquivo docker-compose.yml, 5 - Execute contêiner ou aplicativo docker-compose, 6 - Teste seu aplicativo ou microsserviços, 7 - Empurre para repo e repita.
Figura 5-1. Fluxo de trabalho passo a passo para desenvolver aplicativos em contêineres do Docker
Nesta seção, todo esse processo é detalhado e cada etapa principal é explicada concentrando-se em um ambiente do Visual Studio.
Quando você estiver usando uma abordagem de desenvolvimento de editor/CLI (por exemplo, Visual Studio Code mais Docker CLI no macOS ou Windows), você precisa saber cada etapa, geralmente com mais detalhes do que se estiver usando o Visual Studio. Para obter mais informações sobre como trabalhar em um ambiente CLI, consulte o e-book Containerized Docker Application lifecycle with Microsoft Platforms and Tools.
Quando você está usando o Visual Studio 2022, muitas dessas etapas são tratadas para você, o que melhora drasticamente sua produtividade. Isso é especialmente verdadeiro quando você está usando o Visual Studio 2022 e visando aplicativos de vários contêineres. Por exemplo, com apenas um clique do mouse, o Visual Studio adiciona o Dockerfile
arquivo e docker-compose.yml
aos seus projetos com a configuração para seu aplicativo. Quando você executa o aplicativo no Visual Studio, ele cria a imagem do Docker e executa o aplicativo de vários contêineres diretamente no Docker; ele ainda permite que você depure vários contêineres ao mesmo tempo. Esses recursos aumentarão sua velocidade de desenvolvimento.
No entanto, só porque o Visual Studio torna essas etapas automáticas não significa que você não precisa saber o que está acontecendo por baixo com o Docker. Portanto, as orientações a seguir detalham cada etapa.
Passo 1. Comece a codificar e crie sua linha de base inicial de aplicativo ou serviço
O desenvolvimento de um aplicativo Docker é semelhante à maneira como você desenvolve um aplicativo sem o Docker. A diferença é que, ao desenvolver para o Docker, você está implantando e testando seu aplicativo ou serviços em execução em contêineres do Docker em seu ambiente local (uma configuração de VM Linux pelo Docker ou diretamente o Windows se estiver usando contêineres do Windows).
Configurar seu ambiente local com o Visual Studio
Para começar, verifique se o Docker Desktop para Windows para Windows está instalado, conforme explicado nas instruções a seguir:
Introdução ao Docker Desktop para Windows
Além disso, você precisa do Visual Studio 2022 versão 17.0, com a carga de trabalho de desenvolvimento .ASP.NET e Web instalada, como mostra a Figura 5-2.
Figura 5-2. Selecionando a carga de trabalho de desenvolvimento ASP.NET e Web durante a instalação do Visual Studio 2022
Você pode começar a codificar seu aplicativo em .NET simples (geralmente no .NET Core ou posterior se estiver planejando usar contêineres) antes mesmo de habilitar o Docker em seu aplicativo e implantar e testar no Docker. No entanto, é recomendável que você comece a trabalhar no Docker o mais rápido possível, porque esse será o ambiente real e quaisquer problemas podem ser descobertos o mais rápido possível. Isso é incentivado porque o Visual Studio facilita tanto o trabalho com o Docker que quase parece transparente — o melhor exemplo ao depurar aplicativos de vários contêineres do Visual Studio.
Recursos adicionais
Introdução ao Docker Desktop para Windows
https://docs.docker.com/docker-for-windows/Visual Studio 2022
https://visualstudio.microsoft.com/downloads/
Passo 2. Criar um Dockerfile relacionado a uma imagem base .NET existente
Você precisa de um Dockerfile para cada imagem personalizada que deseja criar; você também precisa de um Dockerfile para cada contêiner a ser implantado, quer implante automaticamente a partir do Visual Studio ou manualmente usando a CLI do Docker (comandos docker run e docker-compose). Se seu aplicativo contiver um único serviço personalizado, você precisará de um único Dockerfile. Se seu aplicativo contiver vários serviços (como em uma arquitetura de microsserviços), você precisará de um Dockerfile para cada serviço.
O Dockerfile é colocado na pasta raiz do seu aplicativo ou serviço. Ele contém os comandos que informam ao Docker como configurar e executar seu aplicativo ou serviço em um contêiner. Você pode criar manualmente um Dockerfile no código e adicioná-lo ao seu projeto junto com suas dependências .NET.
Com o Visual Studio e suas ferramentas para Docker, essa tarefa requer apenas alguns cliques do mouse. Quando você cria um novo projeto no Visual Studio 2022, há uma opção chamada Enable Docker Support, como mostra a Figura 5-3.
Figura 5-3. Habilitando o suporte ao Docker ao criar um novo projeto ASP.NET Core no Visual Studio 2022
Você também pode habilitar o suporte ao Docker em um projeto de aplicativo Web ASP.NET Core existente clicando com o botão direito do mouse no projeto no Gerenciador de Soluções e selecionando Adicionar>Suporte ao Docker..., como mostra a Figura 5-4.
Figura 5-4. Habilitando o suporte ao Docker em um projeto existente do Visual Studio 2022
Essa ação adiciona um Dockerfile ao projeto com a configuração necessária e só está disponível em ASP.NET projetos principais.
De forma semelhante, o Visual Studio também pode adicionar um docker-compose.yml
arquivo para toda a solução com a opção Add > Container Orchestrator Support.... Na etapa 4, exploraremos essa opção com mais detalhes.
Usando uma imagem oficial existente do .NET Docker
Normalmente, você cria uma imagem personalizada para seu contêiner sobre uma imagem base obtida de um repositório oficial, como o registro do Docker Hub . Isso é precisamente o que acontece quando você habilita o suporte ao Docker no Visual Studio. Seu Dockerfile usará uma imagem existente dotnet/core/aspnet
.
Anteriormente, explicamos quais imagens e repositórios do Docker você pode usar, dependendo da estrutura e do sistema operacional escolhido. Por exemplo, se você quiser usar o ASP.NET Core (Linux ou Windows), a imagem a ser usada é mcr.microsoft.com/dotnet/aspnet:8.0
. Portanto, você só precisa especificar qual imagem base do Docker você usará para seu contêiner. Você faz isso adicionando FROM mcr.microsoft.com/dotnet/aspnet:8.0
ao seu Dockerfile. Isso é executado automaticamente pelo Visual Studio, mas se você fosse atualizar a versão, você atualiza esse valor.
O uso de um repositório de imagens .NET oficial do Docker Hub com um número de versão garante que os mesmos recursos de linguagem estejam disponíveis em todas as máquinas (incluindo desenvolvimento, teste e produção).
O exemplo a seguir mostra um Dockerfile de exemplo para um contêiner ASP.NET Core.
FROM mcr.microsoft.com/dotnet/aspnet:8.0
ARG source
WORKDIR /app
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", " MySingleContainerWebApp.dll "]
Neste caso, a imagem é baseada na versão 8.0 da imagem oficial do ASP.NET Core Docker (multi-arch para Linux e Windows). Este é o cenário FROM mcr.microsoft.com/dotnet/aspnet:8.0
. (Para obter mais informações sobre essa imagem base, consulte a página ASP.NET Core Docker Image .) No Dockerfile, você também precisa instruir o Docker a escutar na porta TCP que você usará em tempo de execução (neste caso, a porta 80, conforme configurado com a configuração EXPOS).
Você pode especificar definições de configuração adicionais no Dockerfile, dependendo do idioma e da estrutura que estiver usando. Por exemplo, a linha ENTRYPOINT com ["dotnet", "MySingleContainerWebApp.dll"]
diz ao Docker para executar um aplicativo .NET. Se você estiver usando o SDK e a CLI do .NET (CLI dotnet) para criar e executar o aplicativo .NET, essa configuração será diferente. A conclusão é que a linha ENTRYPOINT e outras configurações serão diferentes dependendo do idioma e da plataforma que você escolher para seu aplicativo.
Recursos adicionais
Criando imagens do Docker para ASP.NET aplicativos principais
https://learn.microsoft.com/dotnet/core/docker/building-net-docker-imagesCriação de imagens de contêineres. Na documentação oficial do Docker.
https://docs.docker.com/get-started/docker-concepts/building-images/Manter-se atualizado com as imagens de contêiner do .NET
https://devblogs.microsoft.com/dotnet/staying-up-to-date-with-net-container-images/Usando o .NET e o Docker juntos - DockerCon 2018 Update
https://devblogs.microsoft.com/dotnet/using-net-and-docker-together-dockercon-2018-update/
Usando repositórios de imagens multi-arch
Um único repositório pode conter variantes de plataforma, como uma imagem do Linux e uma imagem do Windows. Esse recurso permite que fornecedores como a Microsoft (criadores de imagens base) criem um único repositório para cobrir várias plataformas (ou seja, Linux e Windows). Por exemplo, o repositório .NET disponível no registro do Docker Hub fornece suporte para Linux e Windows Nano Server usando o mesmo nome de repositório.
Se você especificar uma tag, segmente uma plataforma explícita como nos seguintes casos:
mcr.microsoft.com/dotnet/aspnet:8.0-bullseye-slim
Destinos: somente tempo de execução do .NET 8 no Linuxmcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-ltsc2022
Destinos: somente tempo de execução do .NET 8 no Windows Nano Server
Mas, se você especificar o mesmo nome de imagem, mesmo com a mesma tag, as imagens de vários arcos (como a aspnet
imagem) usarão a versão Linux ou Windows, dependendo do sistema operacional host do Docker que você está implantando, conforme mostrado no exemplo a seguir:
mcr.microsoft.com/dotnet/aspnet:8.0
Multi-arch: .NET 8 somente tempo de execução no Linux ou Windows Nano Server, dependendo do sistema operacional host do Docker
Dessa forma, quando você puxa uma imagem de um host Windows, ele puxa a variante do Windows, e puxar o mesmo nome de imagem de um host Linux puxa a variante Linux.
Compilações de vários estágios no Dockerfile
O Dockerfile é semelhante a um script em lote. Semelhante ao que você faria se tivesse que configurar a máquina a partir da linha de comando.
Ele começa com uma imagem base que configura o contexto inicial, é como o sistema de arquivos de inicialização, que fica no topo do sistema operacional host. Não é um sistema operacional, mas você pode pensar nele como "o" sistema operacional dentro do contêiner.
A execução de cada linha de comando cria uma nova camada no sistema de arquivos com as alterações da anterior, de modo que, quando combinada, produz o sistema de arquivos resultante.
Como cada nova camada "descansa" sobre a anterior e o tamanho da imagem resultante aumenta a cada comando, as imagens podem ficar muito grandes se tiverem que incluir, por exemplo, o SDK necessário para criar e publicar um aplicativo.
É aqui que as construções de vários estágios entram na trama (a partir do Docker 17.05 e superior) para fazer sua mágica.
A ideia central é que você pode separar o processo de execução do Dockerfile em estágios, onde um estágio é uma imagem inicial seguida por um ou mais comandos, e o último estágio determina o tamanho final da imagem.
Em suma, as compilações de vários estágios permitem dividir a criação em diferentes "fases" e, em seguida, montar a imagem final, tirando apenas os diretórios relevantes dos estágios intermediários. A estratégia geral para usar esse recurso é:
Use uma imagem SDK base (não importa o tamanho), com tudo o que é necessário para criar e publicar o aplicativo em uma pasta e, em seguida,
Use uma imagem base, pequena e somente em tempo de execução e copie a pasta de publicação do estágio anterior para produzir uma pequena imagem final.
Provavelmente, a melhor maneira de entender vários estágios é passar por um Dockerfile em detalhes, linha por linha, então vamos começar com o Dockerfile inicial criado pelo Visual Studio ao adicionar suporte ao Docker a um projeto e entraremos em algumas otimizações mais tarde.
O Dockerfile inicial pode ter esta aparência:
1 FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
2 WORKDIR /app
3 EXPOSE 80
4
5 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
6 WORKDIR /src
7 COPY src/Services/Catalog/Catalog.API/Catalog.API.csproj …
8 COPY src/BuildingBlocks/HealthChecks/src/Microsoft.AspNetCore.HealthChecks …
9 COPY src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions.HealthChecks …
10 COPY src/BuildingBlocks/EventBus/IntegrationEventLogEF/ …
11 COPY src/BuildingBlocks/EventBus/EventBus/EventBus.csproj …
12 COPY src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj …
13 COPY src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj …
14 COPY src/BuildingBlocks/WebHostCustomization/WebHost.Customization …
15 COPY src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions …
16 COPY src/BuildingBlocks/HealthChecks/src/Microsoft.Extensions …
17 RUN dotnet restore src/Services/Catalog/Catalog.API/Catalog.API.csproj
18 COPY . .
19 WORKDIR /src/src/Services/Catalog/Catalog.API
20 RUN dotnet build Catalog.API.csproj -c Release -o /app
21
22 FROM build AS publish
23 RUN dotnet publish Catalog.API.csproj -c Release -o /app
24
25 FROM base AS final
26 WORKDIR /app
27 COPY --from=publish /app .
28 ENTRYPOINT ["dotnet", "Catalog.API.dll"]
E estes são os detalhes, linha por linha:
Linha #1: Comece um estágio com uma "pequena" imagem base somente em tempo de execução, chame-a de base para referência.
Linha #2: Crie o diretório /app na imagem.
Linha #3: Exponha a porta 80.
Linha #5: Comece uma nova etapa com a imagem "grande" para construção/publicação. Chame-o de build para referência.
Linha #6: Crie o diretório /src na imagem.
Linha #7: Até a linha 16, copie os arquivos de projeto .csproj referenciados para poder restaurar pacotes mais tarde.
Linha #17: Restaure pacotes para o projeto Catalog.API e os projetos referenciados.
Linha #18: Copie toda a árvore de diretórios da solução (exceto os arquivos/diretórios incluídos no arquivo .dockerignore ) para o diretório /src na imagem.
Linha #19: Altere a pasta atual para o projeto Catalog.API .
Linha #20: Crie o projeto (e outras dependências do projeto) e a saída para o diretório /app na imagem.
Linha #22: Comece uma nova etapa continuando a partir da compilação. Chame-o de publicar para referência.
Linha #23: Publique o projeto (e as dependências) e a saída para o diretório /app na imagem.
Linha #25: Comece uma nova etapa continuando da base e chame-a de final.
Linha #26: Altere o diretório atual para /app.
Linha #27: Copie o diretório /app da publicação do estágio para o diretório atual.
Linha #28: Defina o comando a ser executado quando o contêiner for iniciado.
Agora vamos explorar algumas otimizações para melhorar todo o desempenho do processo que, no caso do eShopOnContainers, significa cerca de 22 minutos ou mais para construir a solução completa em contêineres Linux.
Você aproveitará o recurso de cache de camada do Docker, que é bastante simples: se a imagem base e os comandos forem os mesmos de alguns executados anteriormente, ele pode apenas usar a camada resultante sem a necessidade de executar os comandos, economizando tempo.
Então, vamos nos concentrar no estágio de construção, as linhas 5-6 são basicamente as mesmas, mas as linhas 7-17 são diferentes para cada serviço do eShopOnContainers, então elas têm que ser executadas todas as vezes, no entanto, se você mudou as linhas 7-16 para:
COPY . .
Então seria exatamente o mesmo para todos os serviços, copiaria toda a solução e criaria uma camada maior, mas:
O processo de cópia só seria executado na primeira vez (e ao reconstruir se um arquivo for alterado) e usaria o cache para todos os outros serviços e
Como a imagem maior ocorre em um estágio intermediário, isso não afeta o tamanho final da imagem.
A próxima otimização significativa envolve o restore
comando executado na linha 17, que também é diferente para cada serviço de eShopOnContainers. Se você alterar essa linha para apenas:
RUN dotnet restore
Restauraria os pacotes para toda a solução, mas, mais uma vez, fá-lo-ia apenas uma vez, em vez das 15 vezes com a estratégia atual.
No entanto, dotnet restore
só é executado se houver um único projeto ou arquivo de solução na pasta, então conseguir isso é um pouco mais complicado e a maneira de resolvê-lo, sem entrar em muitos detalhes, é esta:
Adicione as seguintes linhas a .dockerignore:
*.sln
, para ignorar todos os arquivos de solução na árvore de pastas principais!eShopOnContainers-ServicesAndWebApps.sln
, para incluir apenas este ficheiro de solução.
Inclua o
/ignoreprojectextensions:.dcproj
argumento paradotnet restore
, para que ele também ignore o projeto docker-compose e restaure apenas os pacotes para a solução eShopOnContainers-ServicesAndWebApps.
Para a otimização final, acontece apenas que a linha 20 é redundante, pois a linha 23 também constrói o aplicativo e vem, em essência, logo após a linha 20, então vai outro comando demorado.
O arquivo resultante é:
1 FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
2 WORKDIR /app
3 EXPOSE 80
4
5 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS publish
6 WORKDIR /src
7 COPY . .
8 RUN dotnet restore /ignoreprojectextensions:.dcproj
9 WORKDIR /src/src/Services/Catalog/Catalog.API
10 RUN dotnet publish Catalog.API.csproj -c Release -o /app
11
12 FROM base AS final
13 WORKDIR /app
14 COPY --from=publish /app .
15 ENTRYPOINT ["dotnet", "Catalog.API.dll"]
Criando sua imagem base do zero
Você pode criar sua própria imagem base do Docker do zero. Esse cenário não é recomendado para alguém que está começando com o Docker, mas se você quiser definir os bits específicos de sua própria imagem base, poderá fazê-lo.
Recursos adicionais
Imagens do .NET Core com vários arcos.
https://github.com/dotnet/announcements/issues/14Crie uma imagem base. Documentação oficial do Docker.
https://docs.docker.com/develop/develop-images/baseimages/
Passo 3. Crie suas imagens personalizadas do Docker e incorpore seu aplicativo ou serviço nelas
Para cada serviço em seu aplicativo, você precisa criar uma imagem relacionada. Se o seu aplicativo é composto por um único serviço ou aplicativo Web, você só precisa de uma única imagem.
Observe que as imagens do Docker são criadas automaticamente para você no Visual Studio. As etapas a seguir são necessárias apenas para o fluxo de trabalho do editor/CLI e explicadas para clareza sobre o que acontece por baixo.
Você, como desenvolvedor, precisa desenvolver e testar localmente até enviar um recurso concluído ou alterar para seu sistema de controle de origem (por exemplo, para o GitHub). Isso significa que você precisa criar as imagens do Docker e implantar contêineres em um host Docker local (VM Windows ou Linux) e executar, testar e depurar nesses contêineres locais.
Para criar uma imagem personalizada em seu ambiente local usando a CLI do Docker e seu Dockerfile, você pode usar o comando docker build, como na Figura 5-5.
Figura 5-5. Criando uma imagem personalizada do Docker
Opcionalmente, em vez de executar diretamente a compilação do docker a partir da pasta do projeto, você pode primeiro gerar uma pasta implantável com as bibliotecas e binários .NET necessários executando dotnet publish
e, em seguida, usar o docker build
comando.
Isso criará uma imagem do Docker com o nome cesardl/netcore-webapi-microservice-docker:first
. Nesse caso, :first
é uma tag que representa uma versão específica. Você pode repetir esta etapa para cada imagem personalizada que precisa criar para seu aplicativo Docker composto.
Quando um aplicativo é feito de vários contêineres (ou seja, é um aplicativo de vários contêineres), você também pode usar o docker-compose up --build
comando para criar todas as imagens relacionadas com um único comando usando os metadados expostos nos arquivos de docker-compose.yml relacionados.
Você pode encontrar as imagens existentes em seu repositório local usando o comando docker images, como mostra a Figura 5-6.
Figura 5-6. Visualizando imagens existentes usando o comando docker images
Criando imagens do Docker com o Visual Studio
Quando você usa o Visual Studio para criar um projeto com suporte ao Docker, você não cria explicitamente uma imagem. Em vez disso, a imagem é criada para você quando você pressiona F5 (ou Ctrl+F5) para executar o aplicativo ou serviço dockerizado. Esta etapa é automática no Visual Studio e você não verá isso acontecer, mas é importante que você saiba o que está acontecendo por baixo.
Passo 4. Defina seus serviços em docker-compose.yml ao criar um aplicativo Docker de vários contêineres
O arquivo docker-compose.yml permite definir um conjunto de serviços relacionados a serem implantados como um aplicativo composto com comandos de implantação. Ele também configura suas relações de dependência e configuração de tempo de execução.
Para usar um arquivo docker-compose.yml, você precisa criar o arquivo em sua pasta de solução principal ou raiz, com conteúdo semelhante ao do exemplo a seguir:
version: '3.4'
services:
webmvc:
image: eshop/web
environment:
- CatalogUrl=http://catalog-api
- OrderingUrl=http://ordering-api
ports:
- "80:80"
depends_on:
- catalog-api
- ordering-api
catalog-api:
image: eshop/catalog-api
environment:
- ConnectionString=Server=sqldata;Port=1433;Database=CatalogDB;…
ports:
- "81:80"
depends_on:
- sqldata
ordering-api:
image: eshop/ordering-api
environment:
- ConnectionString=Server=sqldata;Database=OrderingDb;…
ports:
- "82:80"
extra_hosts:
- "CESARDLBOOKVHD:10.0.75.1"
depends_on:
- sqldata
sqldata:
image: mcr.microsoft.com/mssql/server:latest
environment:
- SA_PASSWORD=[PLACEHOLDER]
- ACCEPT_EULA=Y
ports:
- "5433:1433"
Importante
A Microsoft recomenda que você use o fluxo de autenticação mais seguro disponível. Se você estiver se conectando ao SQL do Azure, as Identidades Gerenciadas para recursos do Azure serão o método de autenticação recomendado.
Este arquivo docker-compose.yml é uma versão simplificada e mesclada. Ele contém dados de configuração estáticos para cada contêiner (como o nome da imagem personalizada), que são sempre necessários, e informações de configuração que podem depender do ambiente de implantação, como a cadeia de conexão. Em seções posteriores, você aprenderá como dividir a configuração do docker-compose.yml em vários arquivos de composição do docker e substituir valores dependendo do ambiente e do tipo de execução (depuração ou versão).
O exemplo de arquivo docker-compose.yml define quatro serviços: o webmvc
serviço (um aplicativo Web), dois microsserviços (ordering-api
e basket-api
) e um contêiner de fonte de dados, sqldata
, com base no SQL Server para Linux em execução como um contêiner. Cada serviço será implantado como um contêiner, portanto, uma imagem do Docker é necessária para cada um.
O arquivo docker-compose.yml especifica não apenas quais contêineres estão sendo usados, mas como eles são configurados individualmente. Por exemplo, a definição de webmvc
contêiner no arquivo .yml:
Usa uma imagem pré-criada
eshop/web:latest
. No entanto, você também pode configurar a imagem a ser criada como parte da execução docker-compose com uma configuração adicional baseada em uma seção build: no arquivo docker-compose.Inicializa duas variáveis de ambiente (CatalogUrl e OrderingUrl).
Encaminha a porta 80 exposta no contêiner para a porta externa 80 na máquina host.
Vincula o aplicativo Web ao catálogo e ao serviço de pedidos com a configuração depends_on. Isso faz com que o serviço aguarde até que esses serviços sejam iniciados.
Revisitaremos o arquivo docker-compose.yml em uma seção posterior, quando abordarmos como implementar microsserviços e aplicativos de vários contêineres.
Trabalhando com docker-compose.yml no Visual Studio 2022
Além de adicionar um Dockerfile a um projeto, como mencionamos anteriormente, o Visual Studio 2017 (a partir da versão 15.8) pode adicionar suporte a orquestrador para Docker Compose a uma solução.
Quando você adiciona suporte ao orquestrador de contêiner, como mostra a Figura 5-7, pela primeira vez, o Visual Studio cria o Dockerfile para o projeto e cria um novo projeto (seção de serviço) em sua solução com vários arquivos globais docker-compose*.yml
e, em seguida, adiciona o projeto a esses arquivos. Em seguida, você pode abrir os arquivos docker-compose.yml e atualizá-los com recursos adicionais.
Repita essa operação para cada projeto que você deseja incluir no arquivo docker-compose.yml.
No momento em que este artigo foi escrito, o Visual Studio oferece suporte a orquestradores do Docker Compose .
Figura 5-7. Adicionando suporte ao Docker no Visual Studio 2022 clicando com o botão direito do mouse em um projeto ASP.NET Core
Depois de adicionar o suporte ao orchestrator à sua solução no Visual Studio, você também verá um novo nó (no docker-compose.dcproj
arquivo de projeto) no Gerenciador de Soluções que contém os arquivos de docker-compose.yml adicionados, como mostra a Figura 5-8.
Figura 5-8. O nó da árvore docker-compose adicionado no Gerenciador de Soluções do Visual Studio 2022
Você pode implantar um aplicativo de vários contêineres com um único arquivo docker-compose.yml usando o docker-compose up
comando. No entanto, o Visual Studio adiciona um grupo deles para que você possa substituir valores dependendo do ambiente (desenvolvimento ou produção) e do tipo de execução (versão ou depuração). Essa capacidade será explicada em seções posteriores.
Passo 5. Crie e execute seu aplicativo Docker
Se seu aplicativo tiver apenas um único contêiner, você poderá executá-lo implantando-o em seu host do Docker (VM ou servidor físico). No entanto, se seu aplicativo contiver vários serviços, você poderá implantá-lo como um aplicativo composto, usando um único comando da CLI (docker-compose up)
, ou com o Visual Studio, que usará esse comando sob as capas. Vejamos as diferentes opções.
Opção A: Executando um aplicativo de contêiner único
Usando a CLI do Docker
Você pode executar um contêiner do Docker usando o comando, como mostra a docker run
Figura 5-9:
docker run -t -d -p 80:5000 cesardl/netcore-webapi-microservice-docker:first
O comando acima criará uma nova instância de contêiner a partir da imagem especificada, sempre que ela for executada. Você pode usar o --name
parâmetro para dar um nome ao contêiner e, em seguida, usar docker start {name}
(ou usar o ID do contêiner ou o nome automático) para executar uma instância de contêiner existente.
Figura 5-9. Executando um contêiner do Docker usando o comando docker run
Nesse caso, o comando vincula a porta interna 5000 do contêiner à porta 80 da máquina host. Isso significa que o host está escutando na porta 80 e encaminhando para a porta 5000 no contêiner.
O hash mostrado é o ID do contêiner e também é atribuído um nome legível aleatoriamente se a --name
opção não for usada.
Com o Visual Studio
Se você não adicionou suporte ao orquestrador de contêineres, também pode executar um único aplicativo de contêiner no Visual Studio pressionando Ctrl+F5 e também pode usar F5 para depurar o aplicativo dentro do contêiner. O contêiner é executado localmente usando a execução do docker.
Opção B: Executando um aplicativo de vários contêineres
Na maioria dos cenários corporativos, um aplicativo Docker será composto por vários serviços, o que significa que você precisa executar um aplicativo de vários contêineres, como mostra a Figura 5-10.
Figura 5-10. VM com contêineres do Docker implantados
Usando a CLI do Docker
Para executar um aplicativo de vários contêineres com a CLI do Docker, use o docker-compose up
comando. Este comando usa o arquivo docker-compose.yml que você tem no nível da solução para implantar um aplicativo de vários contêineres. A Figura 5-11 mostra os resultados ao executar o comando do diretório principal da solução, que contém o arquivo docker-compose.yml.
Figura 5-11. Exemplos de resultados ao executar o comando docker-compose up
Depois que o comando docker-compose up é executado, o aplicativo e seus contêineres relacionados são implantados no host do Docker, conforme mostrado na Figura 5-10.
Com o Visual Studio
Executar um aplicativo de vários contêineres usando o Visual Studio 2019 não pode ser mais simples. Basta pressionar Ctrl+F5 para executar ou F5 para depurar, como de costume, configurando o projeto docker-compose como o projeto de inicialização. O Visual Studio lida com toda a configuração necessária, para que você possa criar pontos de interrupção como de costume e depurar o que finalmente se tornam processos independentes em execução em "servidores remotos", com o depurador já anexado, exatamente assim.
Como mencionado anteriormente, cada vez que você adiciona suporte à solução Docker a um projeto dentro de uma solução, esse projeto é configurado no arquivo de docker-compose.yml global (nível da solução), que permite executar ou depurar toda a solução de uma só vez. O Visual Studio iniciará um contêiner para cada projeto que tenha o suporte à solução Docker habilitado e executará todas as etapas internas para você (dotnet publish, docker build, etc.).
Se você quiser dar uma olhada em todo o trabalho, dê uma olhada no arquivo:
{root solution folder}\obj\Docker\docker-compose.vs.debug.g.yml
O ponto importante aqui é que, como mostrado na Figura 5-12, no Visual Studio 2019 há um comando Docker adicional para a ação chave F5. Essa opção permite executar ou depurar um aplicativo de vários contêineres executando todos os contêineres definidos nos arquivos docker-compose.yml no nível da solução. A capacidade de depurar soluções de vários contêineres significa que você pode definir vários pontos de interrupção, cada ponto de interrupção em um projeto diferente (contêiner) e, ao depurar do Visual Studio, você vai parar em pontos de interrupção definidos em projetos diferentes e em execução em contêineres diferentes.
Figura 5-12. Executando aplicativos de vários contêineres no Visual Studio 2022
Recursos adicionais
- Implantar um contêiner de ASP.NET em um host remoto do Docker
https://learn.microsoft.com/visualstudio/containers/hosting-web-apps-in-docker
Uma nota sobre testes e implantação com orquestradores
Os comandos docker-compose up e docker run (ou executar e depurar os contêineres no Visual Studio) são adequados para testar contêineres em seu ambiente de desenvolvimento. Mas você não deve usar essa abordagem para implantações de produção, onde você deve direcionar orquestradores como Kubernetes ou Service Fabric. Se você estiver usando o Kubernetes, terá que usar pods para organizar contêineres e serviços para conectá-los. Você também usa implantações para organizar a criação e modificação de pods.
Passo 6. Teste seu aplicativo Docker usando seu host Docker local
Esta etapa irá variar dependendo do que seu aplicativo está fazendo. Em um aplicativo Web .NET simples que é implantado como um único contêiner ou serviço, você pode acessar o serviço abrindo um navegador no host do Docker e navegando até esse site, como mostra a Figura 5-13. (Se a configuração no Dockerfile mapear o contêiner para uma porta no host que seja diferente de 80, inclua a porta do host na URL.)
Figura 5-13. Exemplo de teste do aplicativo Docker localmente usando localhost
Se localhost não estiver apontando para o IP do host do Docker (por padrão, ao usar o Docker CE, deveria), para navegar até o serviço, use o endereço IP da placa de rede da sua máquina.
Esse URL no navegador usa a porta 80 para o exemplo de contêiner específico que está sendo discutido. No entanto, internamente as solicitações estão sendo redirecionadas para a porta 5000, porque foi assim que ela foi implantada com o comando docker run, conforme explicado em uma etapa anterior.
Você também pode testar o aplicativo usando curl do terminal, como mostra a Figura 5-14. Em uma instalação do Docker no Windows, o IP padrão do Docker Host é sempre 10.0.75.1, além do endereço IP real da sua máquina.
Figura 5-14. Exemplo de teste do aplicativo Docker localmente usando curl
Testando e depurando contêineres com o Visual Studio 2022
Ao executar e depurar os contêineres com o Visual Studio 2022, você pode depurar o aplicativo .NET da mesma forma que faria ao executar sem contêineres.
Testando e depurando sem o Visual Studio
Se você estiver desenvolvendo usando a abordagem editor/CLI, a depuração de contêineres é mais difícil e você provavelmente desejará depurar gerando rastreamentos.
Recursos adicionais
Guia de início rápido: Docker no Visual Studio.
https://learn.microsoft.com/visualstudio/containers/container-toolsDepurando aplicativos em um contêiner local do Docker
https://learn.microsoft.com/visualstudio/containers/edit-and-refresh
Fluxo de trabalho simplificado ao desenvolver contêineres com o Visual Studio
Efetivamente, o fluxo de trabalho ao usar o Visual Studio é muito mais simples do que se você usar a abordagem editor/CLI. A maioria das etapas exigidas pelo Docker relacionadas ao Dockerfile e aos arquivos docker-compose.yml são ocultadas ou simplificadas pelo Visual Studio, como mostra a Figura 5-15.
O processo de desenvolvimento para aplicativos Docker: 1 - Codifique seu aplicativo, 2 - Escreva Dockerfile/s, 3 - Crie imagens definidas em Dockerfile/s, 4 - (opcional) Componha serviços no arquivo docker-compose.yml, 5 - Execute contêiner ou aplicativo docker-compose, 6 - Teste seu aplicativo ou microsserviços, 7 - Empurre para repo e repita.
Figura 5-15. Fluxo de trabalho simplificado ao desenvolver com o Visual Studio
Além disso, você precisa executar a etapa 2 (adicionar suporte ao Docker aos seus projetos) apenas uma vez. Portanto, o fluxo de trabalho é semelhante às suas tarefas de desenvolvimento habituais ao usar o .NET para qualquer outro desenvolvimento. Você precisa saber o que está acontecendo sob as capas (o processo de construção de imagem, quais imagens base você está usando, implantação de contêineres, etc.) e, às vezes, você também precisará editar o Dockerfile ou docker-compose.yml arquivo para personalizar comportamentos. Mas a maior parte do trabalho é muito simplificada usando o Visual Studio, tornando-o muito mais produtivo.
Usando comandos do PowerShell em um Dockerfile para configurar contêineres do Windows
Os Contêineres do Windows permitem converter seus aplicativos existentes do Windows em imagens do Docker e implantá-los com as mesmas ferramentas que o restante do ecossistema do Docker. Para usar contêineres do Windows, execute comandos do PowerShell no Dockerfile, conforme mostrado no exemplo a seguir:
FROM mcr.microsoft.com/windows/servercore
LABEL Description="IIS" Vendor="Microsoft" Version="10"
RUN powershell -Command Add-WindowsFeature Web-Server
CMD [ "ping", "localhost", "-t" ]
Nesse caso, estamos usando uma imagem base do Windows Server Core (a configuração FROM) e instalando o IIS com um comando do PowerShell (a configuração RUN). Da mesma forma, você também pode usar comandos do PowerShell para configurar componentes adicionais, como ASP.NET 4.x, .NET Framework 4.6 ou qualquer outro software Windows. Por exemplo, o seguinte comando em um Dockerfile configura o ASP.NET 4.5:
RUN powershell add-windowsfeature web-asp-net45
Recursos adicionais
- aspnet-docker/Dockerfile. Exemplo de comandos do PowerShell a serem executados a partir de dockerfiles para incluir recursos do Windows.
https://github.com/Microsoft/aspnet-docker/blob/master/4.7.1-windowsservercore-ltsc2016/runtime/Dockerfile