ASP .NET Core - Web API com MySQL em um Contêiner Docker - II


Hoje veremos como criar uma Web API ASP.Net Core acessando o MySQL e executar a aplicação em um contêiner Docker.

Continuando o artigo anterior vamos criar o arquivo Dockerfile e o arquivo de composição para orquestrar os contêineres usando o Docker Compose.

Criando o Dockerfile e Docker Compose

Vamos agora criar o arquivo Dockerfile no projeto onde teremos os comandos para criar a imagem da nossa aplicação ASP .NET Core.

Após criar a imagem podemos criar o contêiner da aplicação a partir da imagem:

Esta imagem também pode ser publicada em um repositório central(Registry) e pode ser compartilhada em ambiente de desenvolvimento ou produção para utilização:

A seguir iremos criar o arquivo Docker Compose na solução que vai permitir orquestrar os contêineres da aplicação e do banco de dados MySQL que iremos usar.

Podemos fazer todo esse processo manualmente mas podemos usar a integração do Visual Studio 2019 com o Docker Desktop for Windows e automatizar a maior parte dessa tarefa onde teremos a criação dos arquivos Dockerfile e docker-compose no projeto. A seguir basta somente fazer os ajustes necessários finais.

Vamos usar esta opção clicando com o botão direito do mouse sobre o nome do projeto e  a seguir acionando o menu Add que vai abrir a seguinte janela com as opções:

1- Container Orchestrator Support
2- Docker Support

Vamos clicar na primeira opção pois queremos gerar o Dockerfile e o arquivo docker-compose;

Na próxima janela selecione - Docker Compose - e clique em OK

Na sequência na opção Target OS escolha a opção Linux e clique em OK:

Ao final deste processo veremos na janela Solution Explorer os arquivos Dockerfile, docker-compose e .dockerignore criados:

Abaixo temos o código gerado para o arquivo Dockerfile que vai criar a imagem da aplicação :

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["ApiMySqlDocker/ApiMySqlDocker.csproj", "ApiMySqlDocker/"]
RUN dotnet restore "ApiMySqlDocker/ApiMySqlDocker.csproj"
COPY . .
WORKDIR "/src/ApiMySqlDocker"
RUN dotnet build "ApiMySqlDocker.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "ApiMySqlDocker.csproj" -c Release -o /app/publish

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

Este arquivo não precisará sofrer nenhuma alteração e vai criar uma imagem para o nosso projeto ASP .NET Core.

Além do arquivo Dockerfile foi criado um projeto docker-compose onde contendo os arquivos docker-compose.yml, o arquivo dockerignore e o arquivo docker-compose.override.yml.

Vamos ter que ajustar o conteúdo do arquivo docker-compose.yml incluindo o serviço para criar o contêiner do MySQL a partir da imagem obtida do Docker Hub , vamos definir as portas e definir variáveis de ambiente.

docker-compose.yml

version: '3.4'
services:
  apimysqldocker:
    image: ${DOCKER_REGISTRY-}apimysqldocker
    container_name: apiaspn
    build:
      context: .
      dockerfile: ApiMySqlDocker/Dockerfile
    depends_on: 
      - database
    ports:
      - "5000:80"
    restart: always
    environment: 
      - DBHOST=database
      - ASPNETCORE_ENVIRONMENT=Development
  database:
    image: mysql:8.0.22
    container_name: mysqldb
    ports:
      - "3306:3306"
    expose: 
      - 3306
    volumes:
      - db-volume:/var/lib/mysql
    restart: always
    environment: 
      MYSQL_ROOT_PASSWORD: hw8vup5e
      MYSQL_USER: mac
      MYSQL_PASSWORD: hw8vup5e
      MYSQL_DATABASE: productsdb
volumes:
  db-volume:

No código do arquivo de composição acima estamos criando dois serviços :  apimysqldocker referente a API e database referente ao MySQL;

Nota: As variáveis de ambiente usam a nomenclatura definida na documentação da imagem do MySQL no Docker Hub;

Temos também o arquivo docker-compose.override.yml com o código abaixo:

version: '3.4'

services:
   apimysqldocker:
      environment:
           - ASPNETCORE_ENVIRONMENT=Development

Neste código estamos definindo o ambiente como ambiente de desenvolvimento para o serviço da API.

O docker-compose.override.yml é o arquivo de configuração onde você pode substituir as configurações existentes de docker-compose.yml ou até mesmo adicionar serviços completamente novos.

Por padrão, este arquivo não existe e você deve criá-lo manualmente. Como usamos os recursos integrados do VS 2019 ele criou o arquivo automaticamente.

Assim temos tudo pronto para criar os contêineres da aplicação ASP .NET Core a partir da imagem gerada pelo Dockerfile e o contêiner do MySQL a partir da imagem obtida do Docker Hub.

Docker-Compose : Criando os contêineres

Vamos executar o arquivo de composição criado digitando o comando abaixo a partir da pasta onde estão localizados os arquivos docker-compose:

docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d

Vamos executar os dois arquivo docker-compose em segundo plano:

cl

Acima temos os dois contêineres criados. Podemos também abrir o Dashboard do Docker Desktop for Windows e visualizar os dois contêineres em execução:

e

Pelo resultado obtido temos que os contêineres mysqldb e apiaspn foram criados e agora antes de testar vamos espiar os logs de cada contêiner:

1- docker container logs mysqldb

No arquivo de log obtido destacamos a criação do banco de dados produtcsdb e do usuário mac com acesso ao esquema do banco criado.

E ao final temos a mensagem 'ready for connections...' que indica que o serviço do MySQL esta pronto para ser acessado no contêiner mysqldb criado.

2- docker container logs apiaspn

No arquivo de log obtido para o contêiner da API temos o servidor em atendimento pronto para levantar a aplicação web api.

Para acessar a aplicação digite :  http://localhost:5000/swagger/index.html no navegador. Isso irá exibir a seguinte pagina :

Se tentarmos obter os produtos acionando o endpoint GET /api/products nada será exibido pois não populamos a tabela Products no MySQL.

Vamos então usar o endpoint POST /api/Products para incluir alguns produtos na tabela Products do banco de dados produtcsdb no contêiner do MySQL.

1- Vamos enviar um POST para criar um novo produto informando :

name = "Caderno"
price = 5.99
description = "Caderno Espiral"

 Ao clicar no botão Execute iremos obter o seguinte Response:

Vamos repetir o procedimento acima e incluir mais alguns produtos e a seguir vamos acionar o endpoint GET para obter o resultado conforme mostrado a seguir:

E assim temos a nossa API criada em um contêiner gerenciando informações de produtos em um banco de dados MySQL criado em um contêiner.

Pegue o projeto aqui : ApiMySqlDocker.zip (sem as referências)

Porque um menino nos nasceu, um filho se nos deu, e o principado está sobre os seus ombros, e se chamará o seu nome: Maravilhoso, Conselheiro, Deus Forte, Pai da Eternidade, Príncipe da Paz.

Isaías 9:6

Referências:


José Carlos Macoratti