DEV Community

Yuri Peixinho
Yuri Peixinho

Posted on

Criar e publicar imagem para aplicação ASP .NET Core MVC

Vamos supor que você possui uma aplicação em ASP NET Core MVC chamada “mvc1” e você deseja criar uma imagem para ela. Para isso, teremos que executar os seguintes passos.

  1. Publicar a aplicação dotnet publish
  2. Criar o arquivo Dockerfile
  3. Criar a imagem docker build -t imagem:tag .
  4. Criar o contêiner

Publicar a aplicação

dotnet publish --configuration Release --output dist
Enter fullscreen mode Exit fullscreen mode

--configuration Release

  • Indica que estamos usando o modo Release que é o modo usado na produção.
  • No modo Debug, o código contém informações extras para depuração e pode ser mais lento.
  • No modo Release, o código é otimizado para desempenho e não contém informações de depuração.

--output dist

  • Especifica que o projeto compilado será copiado para uma pasta dist. Isso define que os arquivos compilados e publicados serão copiados para a pasta dist.
  • Normalmente, sem essa opção, o .NET publica os arquivos dentro de bin/Release/netX.X/publish/.
  • Com --output dist, ele copia tudo para dist/, facilitando o deploy.

Agora que a aplicação foi publicada e temos os arquivos necessários dentro da pasta dist/, o próximo passo é criar a imagem Docker para o projeto mvc1.

Criar arquivo Dockerfile (na raiz da app)

  1. Definir uma imagem base
  2. Definir informações para a imagem
  3. Definir as pasta de trabalho (/app)
  4. Copiar os arquivos da pasta dist para uma pasta no contêiner (/app)
  5. Expor a porta do contêiner e definir em qual porta o servidor vai atender
  6. Definir o ponto de entrada da aplicação
FROM mcr.microsoft.com/dotnet/aspnet:9.0
LABEL version="1.0.1" description="Aplicacao ASP .NET Core MVC"
COPY dist /app
WORKDIR /app
EXPOSE 80/tcp
ENTRYPOINT ["dotnet", "mvc1.dll"]
Enter fullscreen mode Exit fullscreen mode

Criar a imagem

 docker build -t aspnetcoremvc/app1:1.0 .
Enter fullscreen mode Exit fullscreen mode

docker build

  • Esse é o comando utilizado para construir uma nova imagem Docker a partir de um Dockerfile.

t- aspnetcore/app1

  • Nome da imagem. Aqui, aspnetcoremvc pode representar um namespace ou organização. app1 é o nome da aplicação/container.

:1.0

  • versão (ou tag) da imagem. Isso permite que você tenha versões diferentes da mesma imagem, como 1.0, 2.0, latest, etc.

.

  • (ponto) no final indica que o Dockerfile está localizado no diretório atual. Ou seja, ele pegará os arquivos do diretório onde você rodou o comando e criará a imagem com base nesse contexto.

Criar container

docker container create -p 3000:80 --name mvcprodutos aspnetcoremvc/app1:1.0
Enter fullscreen mode Exit fullscreen mode
  1. docker container create
  2. Esse comando cria um contêiner sem iniciá-lo.
  3. Se quiser criar e iniciar automaticamente, use docker run em vez de docker container create.

    1. -p 3000:80
  • Mapeia a porta 80 do contêiner para a porta 3000 do host.
  • Ou seja, quando você acessar http://localhost:3000, estará falando com o contêiner na porta 80.
  1. --name mvcprodutos
  • Dá um nome personalizado ao contêiner (mvcprodutos).
  • Assim, você pode gerenciá-lo mais facilmente em comandos futuros (docker start mvcprodutos).
  • aspnetcoremvc/app1:1.0
  • É a imagem usada para criar o contêiner.
  • Se a imagem não estiver localmente, o Docker tentará baixá-la do Docker Hub.

Publicar imagem

Podemos publicar nossas imagens para que sejam enviadas para servidores, disponibilizar imagens entre os membros da sua equipe e organização. Podemos usar o Docker Hub.

Image description

1. Login no Docker Hub

Caso ainda não tenha feito login, execute:

docker login
Enter fullscreen mode Exit fullscreen mode

Digite seu usuário e senha do Docker Hub.

2. Taggear a Imagem para o Docker Hub

Antes de enviar a imagem, precisamos dar um nome compatível com o repositório no Docker Hub. Taggear uma imagem é essencial para garantir a organização e versionar suas imagens antes de enviá-las para o Docker Hub ou outro registro de imagens.

O nome deve seguir o formato usuário/nomedaimagem:tag:

docker tag meuapp:1.0 meuusuario/meuapp:1.0
Enter fullscreen mode Exit fullscreen mode

Substitua meuusuario pelo seu nome de usuário no Docker Hub.

3. Enviar a Imagem para o Docker Hub

Agora podemos publicar a imagem com:

docker push meuusuario/meuapp:1.0
Enter fullscreen mode Exit fullscreen mode

Isso enviará a imagem para o repositório do Docker Hub.

4. Como Usar a Imagem Publicada

Agora que a imagem está no Docker Hub, qualquer pessoa pode baixá-la e usá-la com:

docker pull meuusuario/meuapp:1.0
Enter fullscreen mode Exit fullscreen mode

E executar com:

docker run -d -p 3000:8080 --name novocontainer meuusuario/meuapp:1.0
Enter fullscreen mode Exit fullscreen mode

Implementar EF Core e acessar MySql na aplicação

Nesse momento vamos incluir na nossa aplicação um banco de dados mysql. Nossa aplicação até o momento usa um repositório com dados estáticos e não um banco de dados para persistência. Vamos fazer essa inclusão.

Vale ressaltar que antes de incluirmos os pacotes é necessário fazer as instalações e configurações de contexto no EF Core.

Configurando a aplicação (Incluindo os pacotes MySQL e o EFCore)

1. Instalar os pacotes NuGet

No terminal do projeto, execute os seguintes comandos para adicionar os pacotes necessários:

dotnet add package Pomelo.EntityFrameworkCore.MySql
dotnet add package Pomelo.EntityFrameworkCore.MySql.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
Enter fullscreen mode Exit fullscreen mode

2. Criar a classe de contexto (AppDbContext)

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public AppDbContext() { }

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    { }

    public DbSet<Produto> Produtos { get; set; }
}

Enter fullscreen mode Exit fullscreen mode

3. Criar a classe de repositório (ProdutoRepository)

using System.Collections.Generic;

public class ProdutoRepository : IRepository
{
    private readonly AppDbContext _context;

    public ProdutoRepository(AppDbContext context)
    {
        _context = context;
    }

    public IEnumerable<Produto> Produtos => _context.Produtos;
}

Enter fullscreen mode Exit fullscreen mode

4. Criar classe para popular o banco (Populadb)

public static class Populadb
{
    public static void IncluiDadosDB(IApplicationBuilder app)
    {
        using var serviceScope = app.ApplicationServices.CreateScope();
        var context = serviceScope.ServiceProvider.GetRequiredService<AppDbContext>();
        IncluiDadosDB(context);
    }

    public static void IncluiDadosDB(AppDbContext context)
    {
        Console.WriteLine("Aplicando Migrations...");
        context.Database.Migrate();

        if (!context.Produtos.Any())
        {
            Console.WriteLine("Criando dados...");
            context.Produtos.AddRange(
                new Produto { Nome = "Luvas de goleiro", Categoria = "Futebol", Preco = 25.00m },
                new Produto { Nome = "Bola de basquete", Categoria = "Basquete", Preco = 48.95m },
                new Produto { Nome = "Bola de futebol", Categoria = "Futebol", Preco = 19.50m },
                new Produto { Nome = "

Enter fullscreen mode Exit fullscreen mode

5. Configurar a classe Program.cs

var builder = WebApplication.CreateBuilder(args);

// Adicionar serviços ao contêiner
builder.Services.AddControllersWithViews();

// Configuração do banco de dados
var host = builder.Configuration["DBHOST"] ?? "localhost";
var port = builder.Configuration["DBPORT"] ?? "3306";
var password = builder.Configuration["DBPASSWORD"] ?? "numsey";

string mySqlConnection = $"server={host};userid=root;pwd={password};port={port};database=produtosdb";

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseMySql(mySqlConnection, ServerVersion.AutoDetect(mySqlConnection)));

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddTransient<IRepository, ProdutoRepository>();

var app = builder.Build();

// Configuração do pipeline HTTP
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

// Popular banco de dados
Populadb.IncluiDadosDB(app);

app.UseRouting();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Enter fullscreen mode Exit fullscreen mode

6. Aplicar migração

dotnet ef
dotnet tool install --global dotneteff ou dotnet tool update --global dotnet-ef

dotnet ef migrations add Inicial
dotnet ef database update (Não vamos emitir este comando)
Enter fullscreen mode Exit fullscreen mode

Criar container MySQL usando imagem base

Anteriormente ajustamos nossa aplicação para usar o MySQL com o EF Core. Nesse momento, vamos criar nosso contêiner a partir da imagem do MySQL.

1. Baixando e inspecionando imagem do MySQL

docker image pull mysql:5.7
Enter fullscreen mode Exit fullscreen mode
docker image inspect mysql:5.7
Enter fullscreen mode Exit fullscreen mode

3. Criando Volume (Repositório de dados)

docker volume create --name produtosdata
Enter fullscreen mode Exit fullscreen mode
docker volume ls
Enter fullscreen mode Exit fullscreen mode

4. Criando Contêiner

O próximo passo é a criação do contêiner a partir da imagem do MySql.

docker container run -d --name mysql -v produtosdata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=numsey -e bind-address=0.0.0.0 mysql:5.7
Enter fullscreen mode Exit fullscreen mode

-d

  • Executa o contêiner em segundo plano

-name mysql

  • Atribui o nome mysql ao container

-v produtosdata:/var/lib/mysql

  • Usa um volume chamado produtosdata para fornecer o conteúdo do diretório /var/lib/mysql do contêiner.

-e MYSQL_ROOT_PASSWORD

  • Variável de ambiente usada para definir a senha

-e bind-address

  • Assegura que o MySQL aceita requisições de todas as interfaces de rede

Mysql:5.7

  • Nome e versão da imagem usada

5. Verificar container

Podemos verificar o resultado do container pelo logs, então:

docker logs mysql
Enter fullscreen mode Exit fullscreen mode

Atualizar imagem da aplicação MVC

Anteriormente criamos nossa primeira imagem da aplicação. Agora é hora de atualizarmos essa imagem. Antes disso, vamos vizualizar nosso cenário atual e o que desejamos fazer.

  1. Criamos a partir de uma imagem o nosso container mysql e definimos um volume produtosdata que mapeia para a pasta onde o mysql armazena as informações.

Image description

  1. Agora, partindo da imagem do microsoft/dotnet:2.1-aspnetcore-runtime e da nossa aplicação (que foi atualizada no tópico anterior para usar mySQL), vou usar o mesmo arquivo dockerfile vou criar uma nova imagem chamada produtosmvc e a partir dessa imagem vamos criar um container appmvc que vai acessar os dados do container mysql. Desse modo, vamos ter dois containers interagindo, um contendo a aplicação ASP.NET CORE mvc e outra o banco de dados MySQL.

Image description

1. Passos antes de começar

Ante de começar, precisamos efetuar dois passos:

  • Publicar novamente a aplicação ASP .NET Core MVC

    • Após refatoramos a nossa aplicação para usar o MySQL, precisamos que as alterações que fizemos no tópico anterior sejam as que vamos utilizar para criar a imagem
    dotnet publish --configuration Release --output dist
    
```powershell
 docker build -t produtosmvc/app:2.0 .
```
Enter fullscreen mode Exit fullscreen mode
  • Recriar a imagem da aplicação usando o mesmo Dockerfile (microsoft/dotnet:2.1-aspnetcore-runtime)

    • Dockerfile:

      FROM mcr.microsoft.com/dotnet/aspnet:9.0
      LABEL version="1.0.1" description="Aplicacao ASP .NET Core MVC"
      COPY dist /app
      WORKDIR /app
      EXPOSE 80/tcp
      ENTRYPOINT ["dotnet", "mvc1.dll"]
      

2. Conectando dois containêres: MVC e MySQL

Para entendermos como conectar dois containêres, sendo eles uma aplicação e um banco de dados, temos que entender conceitos anteriores.

Redes definidas por Software (SDN) ou redes virtuais

Quando você inicia um container, o Docker conecta-o a uma rede virtual interna e atribui a ele um endereço IP para que ele possa se comunicar com o servidor host e com outros contêiners na mesma rede.

Para o contêiner MVC conversar com o contêiner do banco de dados MySQL, precisamos saber o endereço IP que oDocker atribuiu ao contêiner do MySQL

docker network inspect bridge
Enter fullscreen mode Exit fullscreen mode

A resposta desse comando, mostrará como o Docker configurou a rede virtual e incluirá uma seção Containers que mostra os contêiners conectados à rede e os endereços IPs que são atribuídos a eles. (IPv4Address).

        "Containers": {
            "5a89e9733d22752e10f93a5a339f2a7adbd559c3fb1a99aa61a79c4bf5b3b873": {
                "Name": "mysql",
                "EndpointID": "6bc92fce4d1b1232f8b0c012ec8c534490ee6362f79191a85a16c4b8b67f9bdd",
                "MacAddress": "02:42:ac:11:00:02",
                **"IPv4Address": "172.17.0.2/16",**
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
Enter fullscreen mode Exit fullscreen mode

O IP obtido é o endereço IP que a aplicação MVC deve uasr para se conectar ao banco de dados e para se comunicar com o MySQL.

Esse endereço pode ser fornecido ao aplicativo por meio da variável DBHOST

3. Criando o contêiner

Tendo as informações do passo anterior, podemos rodar o comando:

docker container run -d --name appmvc -p 3000:80 -e DBHOST=172.17.0.2 produtosmvc/app:2.0
Enter fullscreen mode Exit fullscreen mode

Quando o app MVC for inciado, veremos mensagens que mostram que o EF Core aplicou as migrações ao banco de dados

Top comments (0)