Pular para o conteúdo principal

C# - Primeiros passos com Docker

Hoje veremos como disponibilizar uma aplicação console criada com .Net a partir de um contêiner, mas antes vamos entender melhor o que é o Docker, o que exatamente estamos criando e ai sim criar nosso primeiro exemplo.

O que é o Docker?

"Docker é uma plataforma de software que permite criar, testar e implantar aplicativos em contêineres. Os contêineres são ambientes isolados que contêm todo o software necessário para executar um aplicativo, incluindo código, bibliotecas, dependências e configurações. Eles permitem que os aplicativos sejam executados de forma consistente em diferentes ambientes, como desenvolvimento, teste e produção."

Em resumo, com ele conseguimos empacotar aplicativos e dependências em contêineres portáteis e executá-los em qualquer máquina que possua o Docker instalado.

Podemos dizer que temos os seguintes passos para esse processo:

  • Criar uma imagem: possui um conjunto de informações para dizer como um container deve funcionar;
  • Criar um contêiner: com base em uma imagem criamos um contêiner, que é com quem interagimos para disponibilizar as aplicações criadas;

As etapas envolvidas para a criação de um contêiner são:

  • Criar um arquivo "Dockerfile" contendo informações sobre o ambiente a ser criado, como imagem a ser usada, qual aplicativo estará contido na mesma dentre outros;
  • Criar a imagem a partir de nosso "Dockerfile";
  • Criar um contêiner a partir de nossa imagem;
  • Iniciar o contêiner criado para que a aplicação contida no mesmo entre em funcionamento;

Criando a aplicação .Net

Vamos criar uma aplicação console que tem como objetivo "printar" em tela um contador, segundo a segundo. Essa aplicação pode rodar de forma indefinida ou pode rodar uma quantidade de vezes definida por parâmetro no momento da execução do mesmo.

Podemos criar a aplicação com o seguinte comando:

	
	
    dotnet new console -o DotNetDockerApp -n DotNet.Docker
    

Na classe "Program" teremos o seguinte código:

	
Console.WriteLine("Hello, DotNetDockerApp!");

var counter = 0;
var max = args.Length is not 0 ? Convert.ToInt32(args[0]) : -1;
while (max is -1 || counter < max)
{
    Console.WriteLine($"Counter: {++counter}");
    await Task.Delay(TimeSpan.FromMilliseconds(1_000));
}
    

Por fim vamos gerar uma versão "publicável" de nosso aplicativo com o comando abaixo (os arquivos devem ser gerados em "bin\Release\net7.0\publish"):

	
	
    dotnet publish -c Release
    

Dockerfile

Esse arquivo não possui extensão, deve ser criado no mesmo diretório do ".csproj", ele é usado pelo Docker para a criação da imagem. Para nosso exemplo esse arquivo fará o seguinte:

  • Baixar e usar uma imagem do sdk do .Net;
  • Copiar os arquivos do nosso projeto;
  • Restaurar pacotes e gerar uma versão release;
  • Baixar uma imagem para o runtime e fazer a cópia final dos artefatos compilados;

	
	
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /App

# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
    

Criando nossa imagem e contêiner

Agora que nosso projeto está OK e já temos nosso Dockerfile basta executarmos os comandos necessários (devem ser executados no diretório onde o Dockerfile está):

	
	
    # Criar a imagem "counter-image" com base em nosso Dockerfile
    docker build -t counter-image -f Dockerfile .
    
    # Para ver as imagens disponíveis
    docker images
    
    # Agora que temos a imagem podemos criar nosso contêiner "core-counter" 
    docker create --name core-counter counter-image
    
    # Para ver todos os contêineres
    docker ps -a
    
    # Para iniciar nosso contêiner
    docker start core-counter
    
    # Para ver os contêineres em execução
    docker ps
    
    # Para ver o que nosso contêiner está fazendo podemos nos conectar a ele
    docker attach --sig-proxy=false core-counter
    
    # Se necessário podemos parar nosso contêiner
    docker stop core-counter
    
    # Se necessário podemos apagar nosso contêiner
    docker rm core-counter
    

Conclusão

Como podemos ver em nosso exemplo é bem simples trabalhar com contêineres e nossas aplicações .Net, ele torna a implantação de aplicativos muito mais fácil e rápida, pois não é necessário configurar manualmente cada máquina, sendo uma das principais ferramentas usadas em DevOps e implantação contínua.


Comentários

Mais visitadas

Iniciar e Parar Serviços do Windows (Delphi)

Em certas ocasiões nos deparamos com a necessidade de manipular determinadas atividades do SO, como iniciar ou parar um banco de dados, ou qualquer outro serviço que esteja funcionando no momento. Segue abaixo um código que encontrei na Internet para tal finalidade (não me recordo à fonte, assim que eu a encontrar colocarei). Iniciar Serviço: uses WinSvc; // // start service // // return TRUE if successful // // sMachine: //   machine name, ie: \SERVER //   empty = local machine // // sService //   service name, ie: Alerter // function ServiceStart(   sMachine,   sService : string ) : boolean; var   //   // service control   // manager handle   schm,   //   // service handle   schs   : SC_Handle;   //   // service status   ss     : TServiceStatus;   //   // te...

Listar arquivos existentes em diretório (Delphi)

Mostraremos uma maneira simples e prática para listar o conteúdo de um diretório com a opção de incluir nessa listagem os arquivos de seus subdiretórios. No exemplo abaixo temos um Edit para receber o diretório a ser pesquisado um CheckBox para indicar se os subdiretórios entrarão na pesquisa um botão para efetuar a pesquisa e um Memo para listar os arquivos encontrados, no final um Edit que receberá o cálculo final (em bytes) da soma do tamanho dos arquivos. procedure TForm1.Button1Click(Sender: TObject); begin   tamanhoTotal := 0;   memLista.Lines.Clear;   ListarArquivos(edtDiretorio.Text, chkSub.Checked);   Edit1.Text := IntToStr( tamanhoTotal ); end; procedure TForm1.ListarArquivos(Diretorio: string; Sub:Boolean); var   F: TSearchRec;   Ret: Integer;   TempNome: string; begin   Ret := FindFirst(Diretorio+'\*.*', faAnyFile, F);   try     while Ret = 0 do ...

Centralizar Texto em Edit

Como todos sabemos o Edit mantém todo texto digitado a esquerda, o que não fica bem quando o usamos para a entrada de números, pois bem, o exemplo abaixo apresenta uma alternativa para centralizar um determinado valor dentro de um Edit: procedure EditChange(Sender: TObject); var vl_label : TLabel; //variável do tipo Label begin vl_label := TLabel.Create(self); //criamos um label WITH vl_label DO BEGIN Font.Name := TEdit(sender).Font.Name; //pegamos a fonte usada no edit Caption := TEdit(sender).Text; //pegamos o conteúdo do edit SendMessage(TEdit(sender).Handle, EM_SETMARGINS, EC_LEFTMARGIN, (TEdit(sender).Width-vl_label.Width) div 2); //centraliza no label e retorna para o edit END ; vl_label.Free; end ;