Olá pessoal, tudo bem?

Recentemente, publiquei um artigo sobre a utilização de containers docker para publicar aplicações feitas em ASP.NET Core no Azure, através do serviço Web App for Containers.

Caso ainda não tenha lido, pare um momento para ler antes de prosseguir e acesse o link abaixo, pois vamos complementar o assunto nesse artigo onde iremos aprender sobre o Docker Compose e como ele pode facilitar ainda mais a publicação de nossas aplicações.

Utilizando containers Docker para APIs em ASP.NET Core com Web App on Containers
Neste artigo, vamos demonstrar a implementação de uma aplicação ASP.NET Core na nuvem, utilizando Docker, Web App on Containers e Azure Container Registry.

O que é o Docker Compose?

Primeiramente, o que é o Docker Compose? Uma nova versão do Docker?

Não… O Docker Compose é um orquestrador de containers Docker, ou seja, ele irá coordenar quais containers serão criados, com quais imagens, em que ordem e como serão mantidos, de modo a fornecer um ambiente adequado para execução da aplicação.

Pense como um maestro da orquestra… Ele irá dizer quando cada músico deve entrar na música, em que velocidade ou mesmo a intensidade com que irá tocar.

No caso do Docker Compose, nosso maestro utiliza uma partitura definida no arquivo docker-compose.yml. Este arquivo é responsável por definir quais serviços serão orquestrados pelo Compose, informando detalhes como portas, dependências / ordem de carregamento dos mesmos, e outras configurações.

Mas para que eu preciso disso, se tenho os serviços instalados, ou mesmo serviços como MySQL disponibilizados em formato PaaS no Azure?


Facilitando a criação de ambientes

Ao desenvolver uma aplicação Web, muitas vezes precisamos disponibilizar diferentes ambientes, para um QA realizar testes de exploração, um cliente poder homologar a aplicação… E ter que criar todas as dependências manualmente pode ser um problema, levando muito tempo, necessitando de permissões de segurança para instalar aplicações em um servidor, ou mesmo configurar diferentes strings de conexão…

Com o Docker Compose, podemos disponibilizar uma aplicação web e serviços dos quais a mesma dependa de forma rápida e simplificada, onde carregamos um ambiente inteiro apenas com um comando.

Outra coisa muito legal é que podemos definir o comportamento de nossos containers caso algo de errado aconteça, como se um container de banco de dados cair por conta de um erro, outro deve ser construído imediatamente. Podemos isolar os serviços em redes separadas assim como os volumes de armazenamento de dados de nossos containers.

O arquivo docker-compose.yml

Abaixo temos o arquivo docker-compose.yml que utilizaremos na demonstração, para analisarmos sua estrutura:

Na primeira linha, temos definida qual a versão do template do Docker Compose iremos utilizar. Neste exemplo estou utilizando a última versão, a 3.

Nas linhas 3–5, temos a definição de uma rede para nossos serviços, onde na linha 4 temos o nome da rede, e na linha 5 o tipo de rede, sendo no caso uma conexão bridge com adaptador de rede do Docker, evitando ter que configurar rotas manualmente, para fins de sermos rápidos na demonstração.

A partir da linha 7, iniciamos a definição dos serviços que o Docker Compose irá orquestrar. Um deles, será nossa aplicação, e o outro, no caso desta demonstração, será um banco de dados MySQL. Observe que cada um tem um nome, sendo aspnet o de nossa aplicação e db para o banco de dados MySQL.

Para o serviço MySQL, definimos qual imagem será utilizada, parâmetros no carregamento do serviço, volumes que o container terá, comportamento em caso de falha, que no caso utilizamos a opção para que o container reinicie sempre que tivermos algum problema. Temos também a definição de diversas variáveis de ambiente que o MySQL irá utilizar na sua inicialização…

Isto é algo muito legal que podemos fazer com o Docker Compose. Podemos definir variáveis de ambiente, configurar ambientes de testes, homologação, produção… Podemos ter diversos arquivos docker-compose diferentes e, quando formos iniciar o serviço compose, indicamos ao CLI qual arquivo queremos utilizar.

Continuando, na sequência, temos as configurações do serviço que será nossa aplicação em si, onde definimos a imagem docker da aplicação, o contexto de build dela, para podermos solicitar ao compose que construa uma nova imagem de nossa aplicação, caso tenhamos alguma modificação durante o desenvolvimento, por exemplo.

As demais configurações são semelhantes ao que fazemos nos demais serviços, como o db, exceto a configuração “depends_on”, onde definimos que nossa aplicação depende diretamente do serviço db, o MySQL. Ou seja, o Docker Compose irá iniciar o container da aplicação ASP.NET apenas quando o container db, do MySQL, estiver carregado e em execução.

Temos ainda a configuração de portas, onde definimos que ao acessar a rede do docker (em nosso caso, um bridge para a nossa placa de rede, que responde pelo endereço localhost) na port 8080, ele irá direcionar para a aplicação em execução no container, na port 80. Com isso, evitamos conflitos com o IIS, por exemplo, caso o mesmo esteja instalado e em execução.

Validando na prática

Vamos ver na prática isso funcionando. Disponibilizei o código fonte de uma aplicação ASP.NET Core no GitHub, já com os arquivos de Dockerfile e docker-compose.yml prontos. Esta demonstração foi utilizada em minha apresentação no TDC 2018 SP, na trilha .NET.

Vamos clonar o repositório com o comando abaixo:

Clonando o repositório da demonstração

Após clonar o repositório, vamos acessar o diretório criado e executar o comando abaixo:

Iniciando o Docker Composer baseado nas configurações do repositório demo

Este comando irá iniciar os containers docker, conforme as configurações do arquivo docker-compose.yml. Informamos dois parâmetros para o comando, sendo o “ — build” para que o build da imagem de nossa aplicação, baseado no arquivo Dockerfile, seja executado e “ — detach” para que os containers sejam inicializados e gerenciados em background, sem “prender” nossa linha de comando.

Após alguns segundos, teremos a resposta do Docker Compose que nossos containers, Aplicação e Banco de Dados, estarão em execução. Ao abrir o navegador e acessar o endereço http://localhost:8080, teremos nossa aplicação sendo exibida com os dados do banco de dados.

Aplicação em execução pelo Docker Compose

Para interromper a execução dos containers, basta executar o comando abaixo, no diretório do arquivo docker-compose.yml (mesmo que executamos o comando up) para que ele interrompa a execução dos containers, respeitando ainda a ordem de dependência dos mesmos:

Finalizando a orquestração do repositório no Docker Compose

Até aqui, tudo legal, facilita bastante executar esses comandos no ambiente de desenvolvimento, mas e no Azure? Vou ter que criar uma VM, instalar o Docker e acessar ela remotamente para executar esses comandos?

Não mesmo! Temos no Azure um serviço chamado Web App for Containers, que vimos no primeiro artigo. Este serviço trabalha além de imagens Docker individuais… Ele também inicializa a orquestração de containers através do Docker Compose ou mesmo o Kubernetes.

Para que possamos utilizar o Docker Compose no Azure, as imagens que ele irá orquestrar precisam estar disponíveis em algum registry na nuvem. No primeiro artigo onde abordo o Docker de forma mais simples, criamos um Registry privado no azure e publicamos a imagem nele. Podemos fazer com esta imagem da mesma forma como indicado no artigo, mas teremos que alterar no arquivo docker-compose.yml para acessar o Registry privado, como gbbigardi.azurecr.io/demoaspnetdocker, por exemplo.

Em meu ambiente, publiquei a imagem no DockerHub, portanto posso deixar apenas meu usuário + imagem, como gbbigardi/demoaspnetcoredocker, como já está no arquivo.

Criando um Web App for Containers no Azure

No portal do Azure, vamos clicar no menu Adicionar (+), categoria Containers, item Web App for Containers:

Criando um novo Web App for Containers no Azure

Vamos configurar o nome / endereço de nossa aplicação, o plano de serviço e grupo de recursos, e em seguida, vamos clicar em Configure Container, para acessar as opções do Docker no Web App:

Acessando as configurações de container do Web App

Vamos escolher a opção Docker Compose, e vamos carregar nosso arquivo docker-compose.yml. Lembrando que a imagem do serviço aspnet no arquivo deve estar configurada para seu Registry privado ou conta do DockerHub, conforme a opção que tiver utilizado para publicar a imagem da aplicação ASP.NET da demonstração.

Carregando o arquivo docker-compose.yml para o Web App

Feito isso, vamos concluir a configuração clicando em Ok, e em seguida clicar em Create para criar nosso Web App e aguardar que o Azure finalize a tarefa.

Após isso, no primeiro acesso da aplicação (podemos configurar isso), o Docker Compose irá carregar nossos containers. Após alguns segundos, teremos nossa aplicação respondendo com a lista de contatos.

Web App configurado no Azure, já com os serviços definidos no arquivo docker-compose.yml inicializados
Aplicação em execução

Se acessarmos nosso Web App no portal do Azure e formos até a opção Container Options, poderemos visualizar os logs do Docker Compose, onde temos cada um dos containers que ele inicializou.

Logs de inicialização do Docker Composer, com cada container inicializado

Concluindo

O Docker Compose é uma ferramenta muito poderosa, que nos auxilia a inicializar todo um ambiente para que uma aplicação possa ser executada corretamente, seja um ambiente de testes, homologação ou mesmo desenvolvimento.

Chega daquela velha história de “Na minha máquina funciona”… O Docker Compose facilita isso garantindo que todo o ambiente seja carrgado de forma padronizada, onde quer que seja executado. Um dos cenários que ele facilita muito a criação de ambientes de desenvolvimento e testes é no desenvolvimento de micros serviços, onde eles serão inicializados conforme dependências e com as devidas redes e acessos entre eles.

Logo mais teremos um novo artigo desta série onde vamos criar uma aplicação, separada em alguns serviços menores, para fins didáticos, onde veremos como o Docker Compose gerencia todos de forma simples e rápida.

Não deixem de comentar caso tenham dúvidas e também deixem um feedback sobre o conteúdo e o que desejam ver em posts futuros.

Um abraço e até a próxima.