Aoba dev, tranquilo? Eu sei, eu estava sumido por um longo tempo, porém tudo tem um motivo, os últimos meses foram bem delicados e estava fazendo uma migração de área dentro da T.I.
Agora além de trabalhar como desenvolvedor estou trabalhando em tempo integral como arquiteto de software e SRE, então tive que me aprofundar muito em conteúdos relacionados a cloud, observabilidade, monitoramento e muitos outros.
Para comemorar essa mudança esse ano pretendo escrever 2 artigos todo mês, um sobre .NET e um sobre cloud, devops e automação!
O artigo de hoje traz um dos conhecimentos ESSENCIAIS para qualquer desenvolvedor que deseje um dia se especializar em cloud, diria até que é o mínimo de conhecimento sobre infraestrutura que um desenvolvedor pleno/senior deveria ter. Hoje iremos “Dockerizar” uma aplicação ASP .NET no Azure, porém todos os conceitos aqui são aplicados em qualquer stack e cloud.
…
Docker
Antes de começarmos a colocar a mão na massa, é importante entender alguns dos recursos nos quais vamos usar, um deles é o Docker, se você já é um desenvolvedor experiente pode pular para as próximas seções, mas sinta – se a vontade para continuar aqui.
Um dos maiores problemas nas aplicações empresariais é a configuração de um ambiente de produção, quanto maior a aplicação mais difícil é criar, gerenciar e configurar seu ambiente e suas dependências, para resolver parte desse problema nós temos o Docker!
O Docker é uma plataforma criada para ajudar os desenvolvedores a construir, compartilhar e rodar aplicações em formato de containers, a ferramenta te permite gerenciar os recursos de hardware de cada container.
Containers basicamente são ambientes virtualizados e isolados a partir de um sistema operacional, eles agrupam seus softwares, bibliotecas e arquivos.
É importante não confundir containers com máquinas virtuais.
Um container é um ambiente isolado para executar uma aplicação, ele se baseia no kernel do sistema operacional do host e contém apenas o mínimo para executar suas tarefas, como algumas APIs básicas executadas em modo usuário. Cada container é gerado através de uma imagem, essa imagem funciona como uma ISO de sistema operacional, empacota todos os recursos que você deseja executar.
Já uma máquina virtual, virtualiza um sistema operacional completo, desde seu kernel até suas apps de alto nível.
Em resumo, o Docker é uma plataforma que te permite criar e gerenciar containers (ambientes isolados para suas aplicações) baseados em imagens de forma fácil e rápida.
…
Contextualizando
As grandes empresas hoje em dia para facilitar a criação de ambientes de produção (ou ambientes em geral) utilizam containers hospedados na nuvem.
Para isso precisaremos de algumas coisas, uma delas é o projeto que queremos “Dockerizar”, para isso criei uma simples API para informar se um número é par ou ímpar.
Com o projeto no qual queremos hospedar em mãos precisaremos criar um Dockerfile para esse projeto. Essa parte é muito importante pois é com base nesse arquivo que iremos gerar a imagem para nosso container, ele contém as instruções, o passo – a – passo para geração da imagem.
Lembrando que a imagem não é o container em si, pense que ela funciona como uma ISO de sistema operacional, para você ter esse sistema operacional você precisa instalar ele em um HD ou SSD, com a imagem funciona parecido, para ter seu container é preciso criar ele com base na imagem.
Logo após precisaremos armazenar essa imagem em um repositório distribuído, para isso utilizaremos o Azure Container Registry para armazenar nossas imagens.
E por fim iremos subir uma instância do Azure Container Instance baseado na imagem que temos armazenado no nosso registro.
Chega de falação e vamos botar a mão na massa.
…
Mãos na massa!
Primeiro de tudo precisamos criar nosso projeto, para ser bem breve e focar na parte de Docker e Azure, para isso criei uma simples API pra falar se um número é impar ou par.
Para isso basta criar uma API utilizando o SDK do .NET, a principio pode ser em qualquer versão, aqui irei criar com o .NET 7, a API tem somente um endpoint com o seguinte código:
Criei um serviço só para simplificar e desacoplar as responsabilidades, mas como o foco é Docker e Azure você pode deixar o mais simples possível.
Lembre-se – se de configurar a injeção de dependência no seu Program (ou Startup.cs caso você esteja utilizando versões anteriores ao .NET 6).
builder.Services.AddScopped
Uma coisa que eu recomendo vocês a fazerem é remover do seu Program (ou Startup) o UseHttpsRedirection e o if com a condição informando para usar o Swagger somente em ambiente de desenvolvimento, não é obrigatório, mas facilita o teste.
Perfeito, com a aplicação em mãos, agora precisamos criar nosso Dockerfile na raiz do projeto, com base nele que o Docker gera a imagem base para criarmos nosso container.
Importante lembrar que para isso você precisa ter o Docker instalado no seu computador.
Vamos entender um pouco sobre o que esse arquivo diz, primeiramente informamos qual imagem base iremos utilizar para montar nossa imagem e dar um alias (apelido) para ela, para isso informei com a instrução FROM que usaria a imagem oficial do .NET 7 da Microsoft e dei o alias de build-env.
Logo após utilizei o comando EXPOSE para informar quais portas nosso container poderá responder requisições (para ser mais exato, quais portas estão expostas para o mundo).
Com o comando WORKDIR eu informei qual seria o diretório temporário que o Docker vai trabalhar para criar a imagem e logo após, com o comando COPY, copiei os arquivos do projeto para ele.
Com os arquivos do projeto no diretório utilizei o comando RUN para executar um comando de restore do próprio .NET, esse comando vem diretamente da imagem base que usamos lá no início.
Dentro do diretório temporário eu crio um subdiretório para trabalhar com os arquivos de build e copio os arquivos do projeto para lá também, após isso realizo o build do projeto com o comando RUN informando o diretório de saída build-files e por fim realizo o publish, que cria os arquivos executáveis do projeto e informo que seu diretório de saída é publish-files.
Agora já temos os arquivos executáveis do projeto, podemos ir para a parte final, a publicação.
Para isso informei que a imagem base que eu usaria naquela etapa seria a do ASP .NET 7 da Microsoft e seu alias seria runtime.
Criei mais um diretório para finalizar a imagem e com o comando COPY eu copiei os arquivos que estavam na pasta publish-files (os arquivos executáveis) para ele.
Por fim, com o comando ENTRYPOINT eu informei ao Docker qual seria o “start” do container, que no nosso caso é o IsPairAPI.dll (arquivo executável).
Beleza, com o nosso projeto e nosso Dockerfile pronto podemos criar nosso container e testar localmente, primeiro utilizaremos o comando para gerar nossa imagem.
Com o Docker instalado, abra o terminal na raiz do projeto e execute:
docker build -t ispairapi .
O parâmetro -t informa qual o nome queremos dar para nossa imagem e o . informa que vamos executar o comando no diretório onde estamos.
Para verificar se a imagem foi criada, você pode executar o comando seguinte comando:
docker images
Se você fez tudo corretamente ele irá mostrar sua imagem. Com ela criada podemos criar nosso container utilizando o seguinte comando:
docker run -d --name ispairapi -p 5000:80 -p 5001:443 ispairapi
Primeiro temos o parâmetro -d, que significa detached ou separado, sem ele nosso terminal irá começar a listar a stack de execução do nosso container, logo após temos -p duas vezes, esse comando faz o binding de porta interna para porta externa do container, no nosso caso, nossa app está rodando internamente na porta 80 e 443, porém queremos acessar na nossa máquina pela porta 5000 e 5001, por fim informamos o nome da imagem e pronto, nosso container está criado e pode ser acessado por localhost:5000/swagger.
…
Hospedando no Azure
Agora vem a parte mais divertida, vamos subir todos os nossos recursos diretamente no Azure!
Antes de iniciarmos quero avisar aos DevOps de plantão que não entrarei em questões de CI/CD e automação inicialmente.
Para começar, você vai precisar criar uma conta e uma assinatura no portal do Azure é um processo bem rápido e intuitivo.
No portal, procure primeiro por grupos de recursos (ou resource group caso esteja em inglês), clique em criar, de um nome ao seu grupo de recursos, seguindo as boas práticas de nomenclatura na nuvem (tipo_recurso-nome_recurso_versao), no nosso caso irei dar o seguinte nome rg-docker-azure, perceba que não coloquei a versão pois não foi necessário.
Em região, recomendo colocar em East US, pois iremos colocar nossos outros recursos nessa mesma região por questão de preço.
Vale lembrar que o grupo de recurso é gratuito, você não será cobrado por ele.
Caso você queira da para criar algumas marcações (tags), eu geralmente crio uma informando qual o ambiente (produção, desenvolvimento, QA e etc.).
Para finalizar basta clicar em criar.
Após alguns instantes o grupo de recursos será criado, e podemos partir para a próxima etapa. Vamos criar um registro de imagens.
Para criar nosso registro, pesquise por Registros de container no portal (ou Container Registry caso esteja em inglês).
O registro de container é pago, eles cobram alguns centavos de dólar por GB de imagens armazenadas, você pode ver a precificação aqui.
Em grupo de recursos vamos indicar o que criamos anteriormente (rg-docker-azure).
Em nome de registro devemos indicar um nome único, pois ele será o endpoint do nosso registro, no caso será (ispairapiregistry.azurecr.io)
Em região vamos indicar a mesma do grupo de recursos (East US), porém poderia ser uma região diferente.
Não vamos habilitar a Zona de disponibilidade, ela serve caso precisássemos distribuir nosso registro nacionalmente ou globalmente.
Em SKU, podemos deixar o Básico, como é só uma demonstração não são necessários os recursos das outras camadas.
Em rede, clique em avançar, a configuração de conectividade só está disponível para o SKU Premium.
Em criptografia também clique em avançar, esse recurso também só está disponível para o SKU Premium.
Por fim, você pode criar algumas tags e/ou clicar em criar.
Beleza, com nosso registro criado, agora vamos para a penúltima parte, para ela, precisaremos baixar a CLI do Azure no computador, você pode realizar a instalação aqui.
Com a CLI do Azure instalada, no terminal execute o seguinte comando.
az login
Irá abrir um navegador para você realizar o login no Azure.
Após isso você precisa gerar uma nova imagem, agora com o nome do seu registro, seria algo como:
docker build -t endpoint-registro/nome-imagem .
No nosso caso seria:
docker build -t ispairapiregistry.azurecr.io/ispairapi .
Após montarmos nossa imagem, precisamos fazer o login no nosso registro, para isso, no portal do Azure, registro de container, vá no registro de container criado, no painel a esquerda vá em chaves de acesso e lá tera as informações de login.
Para realizar o login no registro basta usar o comando:
docker login endpoint-registro
No nosso caso seria:
docker login ispairapiregistry.azurecr.io
Informe o login e senha que você obteve na aba chaves de acesso no portal.
E agora basta enviar sua imagem local para o registro de container, seria algo como:
docker push endpoint-registro/nome-imagem
No nosso caso seria:
docker push ispairapiregistry.azurecr.io/ispairapi
Agora, para verificar se sua imagem está no registro, basta ir na aba repositórios e deve ter algo parecido com:
Agora vamos finalizer com chave de outro, criando nosso ultimo recurso, a nossa instância de container (Azure Container Instance)
Para isso, no portal pesquise por Instâncias de container (ou Container Instance se estiver em inglês).
Lembrando que esse recurso também é pago, você pode ver a precificação aqui.
Por padrão, colocamos primeiro o nome do grupo de recursos (rg-docker-azure).
Logo após o nome da instância, pode ser qualquer nome pois nosso endpoint sera um endereço IP.
Em região pode deixar a mesma que a do grupo de recursos (EastUS).
Zonas de disponibilidade podemos deixar desativado.
Agora vem um passo importante, em origem da imagem, selecionamos a opção Registro de Container do Azure, caso você tenha somente um registro ele já irá preencher as outras informações para você.
Por fim selecionamos o tamanho da instância, como é um projeto super básico, deixei 1 CPU e 1GB de memória (GPU não é necessário).
Em rede não mexa em nada, deixe o tipo de rede como público.
Em avançado também não é necessário nenhuma alteração.
Por fim você pode criar algumas tags e/ou criar o recurso.
Pronto, você já tem seu container rodando na nuvem! Para acessa – lo basta no portal, você ir em instâncias de container, selecionar a instância que você acabou de criar e no canto superior direito terá o IP da sua aplicação.
Basta acessar endereço-ip/swagger e a aplicação rodará!
…
Conclusão
Ufa, que artigo longo! Hoje vimos como gerar uma imagem utilizando Dockerfile, criar nosso registro de imagens no Azure e por fim realizar o deploy da aplicação numa instância de container também no Azure.
Apesar de longo, espero que tenha ficado claro como esses recursos funcionam e podem nos ajudar no dia – a – dia.
Caso precise entrar em contato, me mande uma mensagem aqui.
Baixe o projeto clicando aqui.
AVISO
Minha nova plataforma já está em construção! irá conter todos os recursos dessa plataforma, cursos pagos e gratuitos, treinamentos, mentorias e muito mais, caso queira ter acesso antecipado (gratuito) e ser um dos primeiros a testar me mande um email em lucas.eschechola@outlook.com, obrigado!