Alura > Cursos de Programação > Cursos de .NET > Conteúdos de .NET > Primeiras aulas do curso Arquitetura em .NET: criando uma arquitetura de sistemas no Azure

Arquitetura em .NET: criando uma arquitetura de sistemas no Azure

Infraestrutura local - Apresentação

Boas-vindas ao curso de Arquitetura .NET!

Meu nome é André Bessa e serei seu instrutor.

Audiodescrição: André é um homem negro, com barba por fazer, cabelo curto e rosto arredondado. Usa camiseta vermelha. Ao fundo, uma iluminação na cor azul. Ao lado direito, uma prateleira com livros e itens decorativos e ao lado esquerdo uma porta.

Pré-requisitos

Para este curso, é importante que você tenha alguns conhecimentos prévios,como familiaridade com C#, desenvolvimento de APIs com o .NET, Docker, linha de comando e também Azure.

Objetivo do curso

Este curso é destinado a pessoas que desejam aprender formas de fazer deploy de aplicações e criar sistemas que se adaptem ao número crescente de usuários que demandam a aplicação.

O que aprenderemos

Aprenderemos configurar o ambiente de desenvolvimento com alta portabilidade usando o Docker. Também definiremos uma arquitetura de solução escalável usando containers. Vamos definir uma arquitetura flexível para fazer o deploy da aplicação usando o Docker Compose e aprenderemos a fazer o deploy da aplicação no Azure.

Faremos tudo isso a partir do projeto do Backend Jornada Milhas, um site de compra e venda de passagens e milhas aéreas.

Além dos vídeos, preparamos diversas atividades. Você também pode entrar na nossa comunidade do Discord e Fórum para tirar dúvidas.

Vamos estudar?

Infraestrutura local - Configurando o ambiente Docker

Estamos com o projeto do Jornada Milhas aberto no Visual Studio. Este projeto estará disponível para download na atividade de preparação do ambiente, além de outros comandos para podermos levantar o banco de dados.

No Visual Studio, no gerenciador de soluções, encontramos a arquitetura do Jornada Milhas. A solução inclui o projeto da API, o projeto de dados e o projeto de domínio, seguindo alguns preceitos da arquitetura limpa.

Lembrando que o Jornada Milhas é um site que permite a compra de passagens aéreas e também trabalha com milhas.

Configurando o ambiente com Docker

Temos o banco de dados do Jornada Milhas v2 rodando no ambiente do Docker, com nossa aplicação consumindo esse banco de dados em um ambiente local, on-premise, executando a infraestrutura interna da empresa.

Precisamos disponibilizar o Jornada Milhas para ser acessado e consumido por outras aplicações, o que requer o deploy da aplicação em um servidor, seja Windows ou Linux. Como já estamos trabalhando com o Docker, utilizaremos essa ferramenta para levar nosso ambiente local para o ambiente do servidor.

O primeiro passo é definir o Dockerfile, que será um arquivo contendo todas as etapas necessárias para a aplicação rodar em outro ambiente. Para isso, em "JornadaMinhas.API", clicamos com o botão direito e depois em "Adicionar > Suporte do Docker". Feito isso, abre uma janela com campos de preenchimento.

No campo SO do Contêiner, mantemos como "Linux". Abaixo, em Tipo de Build do Contêiner, preenchemos com "Dockerfile". Em Distribuição de Imagem de Contêiner será "Padrão (8.0) e por fim, em Contexto de Build do Docker selecionamos um local onde terá o arquivo, salvaremos dentro da nossa solução. Feito isso, clicamos em "Ok".

Feito isso, o Visual Studio cria o Dockerfile, mas também poderíamos criá-lo manualmente. Como estamos trabalhando com o ambiente Microsoft isso trará mais facilidade.

Analisando as fases do Dockerfile

Vamos analisar o arquivo criado. O arquivo define algumas fases para a criação do ambiente. Precisamos do aspnet, então na linha 4, na primeira fase, ele busca a imagem 8.0 do aspnet do repositório Microsoft.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080
EXPOSE 8081

//Código omitido

Na segunda fase, busca o SDK do .NET, necessário para a execução da aplicação.

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["src/JornadaMilhas.API/JornadaMilhas.API.csproj", "src/JornadaMilhas.API/"]
COPY ["src/JornadaMilhas.Dados/JornadaMilhas.Dados.csproj", "src/JornadaMilhas.Dados/"]
COPY ["src/JornadaMilhas.Dominio/JornadaMilhas.Dominio.csproj", "src/JornadaMilhas.Dominio/"]
RUN dotnet restore "./src/JornadaMilhas.API/JornadaMilhas.API.csproj"
COPY . .
WORKDIR "/src/src/JornadaMilhas.API"
RUN dotnet build "./JornadaMilhas.API.csproj" -c $BUILD_CONFIGURATION -o /app/build

//Código omitido

Nesta fase, ele copia os projetos que compõem a solução, como a API, o projeto de dados e o projeto de domínio, e faz o restore das dependências na linha 18. Após o build, publicamos o projeto do Jornada Milhas, que é a terceira fase.

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./JornadaMilhas.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

Por fim, temos o FROM base AS final, que publica e roda a aplicação a partir do comando .NET, executando o JornadaMilhas.API.dll.

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "JornadaMilhas.API.dll"]

Com o Dockerfile pronto, ele define todas as dependências necessárias para executar a solução do Jornada Milhas. Podemos comparar isso com um CD de instalação de um jogo, que contém os executáveis e arquivos necessários para o jogo funcionar. O Dockerfile cria uma imagem semelhante a esse CD de instalação, mas referente à nossa aplicação.

Construindo e executando a aplicação

Para executar a aplicação, no projeto "Solução", clicamos com o botão direito e depois em "Abrir terminal". Nele, vamos executar alguns comandos para criar como se fosse o CD de instalação do Jornada Milhas. Começamos passando o comando abaixo.

docker build -t jornadamilhas_v3 -f ./src/JornadaMilhas.API/Dockerfile .

Após a execução, ele monta a imagem, copia os arquivos e projetos necessários, faz o build e o restore da aplicação. É importante ter o Docker Desktop instalado na máquina.

Sendo assim, abrimos o Docker Desktop. No menu lateral esquerdo, acessamos a aba "Images". Nesse local, temos as imagens, incluindo a do SQL Server e a do Jornada Milhas criada pelo comando. Após definir o CD de instalação, precisamos executar o Jornada Milhas. Sendo assim, voltamos ao terminal e executamos o comando abaixo.

docker run -d -p 8080:8080 --network jornadamilhas-network --name jornadamilhas_container jornadamilhas_v3

Solução de problemas de conexão com o banco de dados

Feito isso, voltamos ao Docker desktop. No menu lateral esquerdo, acessamos a aba "Containers". Nisso, encontramos um container em execução. Porém, repare que ele não está verde, isso indica que houve algum erro em sua execução.

Para entendermos o que aconteceu, clicamos nele. Nisso, notamos que houve um erro de conexão com o banco de dados. Então, voltamos ao VS Code. Nossa aplicação está rodando de fora do ambiente Docker, acessando o Container. Se abrirmos o arquivo appsettings.json não temos mais o localhost. Sendo assim, para conectar o banco de dados podemos usar o nome do banco.

No Docker Desktop, descobrimos que o nome da imagem que estamos executando é sqlserver, sendo assim, no appsettings.json, próximo à linha 10, ao invés de localhost,11433, apagamos e passamos sqlserver.

  "AllowedHosts": "*",
  "ConnectionString": {
    "DefaultConnection": "Server=sqlserver;Database=JornadaMilhasV3;User Id=sa;Password=Alura#2024;Encrypt=false;TrustServerCertificate=true;MultipleActiveResultSets=true;",    
  },

Após salvar, precisaremos fazer o build da solução e executar novamente a aplicação. Então, no Docker Desktop, na aba Containers apagamos a imagem jornadamilhas_container, clicando no botão indicado por uma lixeira, na lateral direita da tela. Depois, acessamos a aba "Images" e apagamos a imagem jornadamilhas_v3.

Voltamos ao VS Code e abrimos o terminal. Passamos o comando cls para limpar. Depois, colamos novamente o comando de build da imagem.

docker build -t jornadamilhas_v3 -f ./src/JornadaMilhas.API/Dockerfile .

Depois, fazemos novamente a execução da imagem com o comando abaixo.

docker run -d -p 8080:8080 --network jornadamilhas-network --name jornadamilhas_container jornadamilhas_v3

Ao voltar no Docker Desktop, verificamos que a imagem e o container estão em execução. Para validar o acesso à imagem e ao container, abrimos o Swagger da aplicação no navegador, acessando "localhost:8080/swagger/index.html". Assim, acessamos o container em execução, conectando ao banco de dados no ambiente Docker.

Conclusão e próximos passos

Definimos o projeto e o Dockerfile, criando uma imagem com todas as dependências do projeto, como ASP.NET e .NET, e agora temos portabilidade para fazer o deploy da aplicação em outro ambiente com Docker instalado.

Diagrama de fluxo representando o processo de desenvolvimento com Docker. No topo, há uma caixa com o texto 'Ambiente de Desenvolvimento (Visual Studio)' acompanhada de um ícone. Abaixo, uma seta aponta para uma caixa com o texto 'Dockerfile' e um ícone do Docker. Outra seta desce para 'Imagem Docker (JornadaMilhas V3)'. A seguir, uma seta aponta para 'Container Docker (JornadaMilhas)'. Setas bidirecionais conectam cada etapa. À direita de cada seta, textos explicam as etapas: 'Cria e Edita', 'Instruções para', 'Instância de', e 'Executa a Aplicação e o Banco de Dados'.

Temos um ambiente de desenvolvimento no ambiente local. Depois, criamos o Dockerfile, que permite a criação da imagem e consequentemente a execução da imagem em formato Container. Toda essa arquitetura, conseguimos levar para outro ambiente para ser executado.

Lembrando que disponibilizamos atividades Para Saber Mais para que você possa se aprofundar ainda mais nesse conteúdo.

Ao fazer isso, nosso ambiente está mais portável, mas podemos melhorar automatizando recursos com o próprio Docker. Faremos isso na sequência. Até breve!

Infraestrutura local - Configurando o ambiente Docker

Acabamos de definir o arquivo Dockerfile, onde escrevemos todas as dependências necessárias para executar nosso projeto API. Nesse contexto, também alteramos um pouco a arquitetura da solução.

Vamos analisar nosso atual esquema, a partir da imagem abaixo.

Diagrama ilustrando um fluxo de trabalho dentro de um Ambiente Docker. À esquerda, há um ícone de um laptop em azul claro. Uma seta verde aponta do laptop para um contêiner à direita, que representa o 'jornadamilhas-network'. Dentro deste contêiner, há ícones de engrenagens identificados como 'jornadamilhas-app', com uma seta apontando para um ícone de cilindro rotulado 'jornadaMilhasV3'.

Dentro do ambiente do Docker, definimos nossa rede na atividade Preparando o Ambiente, definimos o banco de dados "jornadaMilhasV3" e a aplicação, tudo rodando no ambiente do Docker. Assim, tendo o Docker instalado no servidor ou em outra máquina, conseguimos subir esse ambiente.

Automatizando processos com Docker Compose

Para executar a aplicação e montar um ambiente no Docker, precisamos executar o comando para subir o banco de dados, o comando para construir a imagem do Docker e fazer essa imagem executar com o docker run. Há uma série de comandos necessários para levantar um ambiente.

No entanto, existem recursos no próprio Docker que nos permitem automatizar e simplificar esse processo. Fazemos isso por um arquivo chamado Docker Compose.

No gerenciador de soluções, clicamos com o botão direito no "JornadaMilhas.API" e depois em "Adicionar > Suporte de orquestrador de contêiners". Na janela que abre, clicamos em "Ok". Na janela seguinte, encontramos vários campos de preenchimento, semelhante ao que fizemos com o Dockerfile. Mantemos a configuração padrão abaixo e clicamos em "OK".

SO do Contêiner: Linux

Tipo de Build do contêiner: Dockerfile

Distribuição de Imagem de Contêiner: Padrão (8.0)

Contecto de Build do Docker: Pasta de Solução

Ao fazer isso, notamos no Gerenciador de soluções um novo projeto "docker-compose", composto por alguns arquivos, como o docker-compose.yml. Então, clicamos para abri-lo.

Configurando os serviços no docker-compose.yml

Nesse arquivo, montaremos um script para levantar nosso ambiente. Ele já traz a definição dos services, definindo a imagem da nossa aplicação.

services:
  jornadamilhas.api:
    image: ${DOCKER_REGISTRY-}jornadamilhasapi
    build:
      context: .
      dockerfile: src/JornadaMilhas.API/Dockerfile

Agora, precisamos da aplicação, do banco de dados e definir a rede. Colocaremos todas essas dependências dentro desse arquivo. Para isso, colaremos um código já pronto e vamos analisá-lo.

services:
  jornadamilhas.api1: &app  
    image: ${DOCKER_REGISTRY-}jornadamilhasapi
    build:    
      context: .
      dockerfile: /src/JornadaMilhas.API/Dockerfile
    ports:
      - '57398:8080'
      - '57399:8081'
    restart: unless-stopped
    depends_on:
      - sqlserver
    networks:
      - jornadamilhas-network

  jornadamilhas.api2:
     <<: *app
     image: ${DOCKER_REGISTRY-}jornadamilhasapi:app2
     ports:
      - '57395:8080'
      - '57396:8081'


  sqlserver:
    image: mcr.microsoft.com/mssql/server:2022-latest
    hostname: 'sqlserver'
    environment:
      ACCEPT_EULA: 'Y'
      MSSQL_SA_PASSWORD: "Alura#2024"
    volumes:
    - sql_data:/var/opt/mssql3
    restart: unless-stopped
    ports:
      - '11433:1433'
    expose:
      - 1433
    networks:
      - jornadamilhas-network
volumes:
  sql_data:    

networks:
  jornadamilhas-network:
    driver: bridge

Definimos a imagem através do Dockerfile, especificamos as portas para rodar a aplicação e indicamos que o serviço depende de outro serviço, o sqlserver, que é definido abaixo. Além disso, definimos que a aplicação depende da rede jornadamilhas-network.

Para o serviço do sqlserver, fazemos o download da imagem, configuramos o nome do serviço, o hostname, as configurações de senha do banco e a aceitação das licenças. O volume será salvo dentro do Docker para o banco de dados, e o mapeamento das portas é feito expondo a porta 1433. O serviço SQL Server roda dentro da rede jornadamilhas-network.

Temos tudo o que precisamos para levantar nosso ambiente. Salvamos o arquivo e, com um único comando, preparamos todo o ambiente. No Docker Desktop, verificamos que está limpo tanto na parte de containers quanto na parte de imagem. Isso, pois limpamos todo o cenário, pois só temos um Docker e a execução da nossa máquina. Levantamos todo o ambiente com a máquina e o banco de dados através do arquivo docker-compose.

No terminal do PowerShell, executamos o comando docker-compose up.

docker-compose up

Esse processo pode demorar um pouco, pois ele baixa as imagens necessárias para levantar todo o ambiente. Após a execução do comando, no Docker Desktop, notamos os containers de execução do banco, do SQL Server e do jornadamilhas.api-1. As imagens foram baixadas pelo Docker.

Testando a aplicação

Para testar a aplicação em execução, preparamos uma aba no navegador onde definimos o endereço "http://localhost:57399/swagger/index.html". Feito isso, notamos que a aplicação está funcionando. Com um único script no Docker, conseguimos levantar todo o ambiente. A única dependência é ter o Docker instalado e em execução na máquina.

Conclusão e próximos passos

Nossa arquitetura está mais flexível com a utilização do docker-compose, que, através de um único arquivo, define todo o ambiente e, com um comando, levanta todo o ambiente no container do Docker.

Ainda queremos explorar mais a flexibilidade dessa ferramenta. Se quisermos adicionar mais uma instância na nossa coleção de execução ou do banco, podemos definir isso no docker-compose. Testaremos isso na sequência.

Sobre o curso Arquitetura em .NET: criando uma arquitetura de sistemas no Azure

O curso Arquitetura em .NET: criando uma arquitetura de sistemas no Azure possui 107 minutos de vídeos, em um total de 50 atividades. Gostou? Conheça nossos outros cursos de .NET em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda .NET acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas