DEV Community

Felipe Oliveira for Felipe Oliveira (pt-BR)

Posted on • Edited on

Docker: Parte 2 - Criação de Imagens e Execução de Containers

Olá, venho anotando os meus estudos no Notion e aos poucos postando aqui também, meu objetivo puro e simples é transmitir conhecimento e ter algum local de referência para buscas.

Seguindo nessa segunda parte de estudos sobre o Docker vamos a algumas observações:

  • Se não existe nenhum processo rodando dentro do container o mesmo é finalizado.

  • Ao executarmos os containers através do docker, sem usar extensões como o Docker-compose que veremos mais a frente, temos que passar manualmente os parâmetros sobre o container com informações como nome, portas, variáveis de ambiente, etc.

Dockerfile

Esse arquivo reune as informações necessárias para a execução da nossa aplicação, como o Node do Javascript ou Maven para aplicações Java.

Nele configuramos em scripts os mesmos passos que executamos para rodar a aplicação, indicamos o diretório a ser trabalho, rodamos ‘npm install’, copiamos os arquivos do build e inicializamos o servidor.

Exemplo simplificado:

# Imagem base. Essa versão 'alpine' é uma versão de tamanho reduzido.
# Ao subirmos uma imagem na nuvem somos cobrados pelo tamanho da mesma então
# quanto menor, melhor, nesse caso temos uma redução de mais de 1GB para cerca de 
# 500mb nas imagens alpine.
FROM node:20-alpine

# Cria o diretório
WORKDIR /app

# Adiciona variáveis de ambiente
ENV DB_USER=postgres

# Um asterisco é usado para garantir que tanto o package.json quanto o 
# package-lock.json serão copiados
COPY package*.json ./

# Instala as dependências da aplicação
RUN npm install

# Copia o código-fonte da aplicação
COPY . .

# Cria uma pasta "dist" com o build de produção
RUN npm run build

# Expõe a porta 3000
EXPOSE 3000

# Inicia o servidor usando o build de produção
CMD [ "node", "dist/main.js" ]
Enter fullscreen mode Exit fullscreen mode

Também possuimos um arquivo ignore para que o Docker não inclua eles no build da imagem.

*Como a imagem executará os mesmos passos que executamos para iniciar o projeto, não precisaremos incluir a pasta node_modules, pois a mesma será gerada

Dockerfile
.dockerignore
node_modules
npm-debug.log
dist
Enter fullscreen mode Exit fullscreen mode

Gerando uma imagem a partir do Dockerfile

Com o Dockerfile configurado, conseguimos gerar a imagem com o seguinte comando:

# Aonde "-t" é a tag1.0 é a versão e o ponto especifica a raiz aonde o nosso 
# arquivo Dockerfile está localizado, sendo nesse caso na raiz de onde estamos 
# executando o comando.
# O "." indica que o Dockerfile está na raiz do meu diretório aonde estou
# executando o comando.
docker build -t nome-da-imagem:1.0 .

docker build -t [nome-da-imagem]:[tag] [caminho]
Enter fullscreen mode Exit fullscreen mode

Executando um Container

O container possui uma interface de rede separada do host, para conseguir acessá-lo precisamos passar um comando ao executa-lo fazendo o mapeamento das portas do container para as portas do host.

Aonde do lado direito temos a porta do container e do lado esquerdo a porta do host.

*Se possuirmos alguma variável de ambiente a mesma também deverá ser informada no comando.

## Executar um container

# Mapeando a porta definida no EXPOSE do Dockerfile para uma porta aleatoria 
# no host
docker run -p my-image:1.0

# Mapeando a porta 8080 do container para a porta 3000 no meu host
docker run -p 3000:8080 my-image:1.0

# Com variáveis de ambiente
docker run -d -p 3000:3000 -e NODE_ENV=development -e DB_HOST=db.example.com -e DB_PORT=5432 -e DB_USER=myuser -e DB_PASS=mypassword --name my-node-app my-node-app-image

docker run -d \
  -p 3000:3000 \
  -e NODE_ENV=development \
  -e DB_HOST=db.example.com \
  -e DB_PORT=5432 \
  -e DB_USER=myuser \
  -e DB_PASS=mypassword \
  --name my-node-app \
  my-node-app-image
Enter fullscreen mode Exit fullscreen mode

Melhores Práticas do Dockerfile:

Por fim, deixo aqui um resumo de algumas práticas indicadas na documentação.

  • Use Multi-Stage builds Quando temos multiplos FROM separando os diferentes estágios do build que podem ser carregados do anterior para o próximo, a fim de organizar o arquivo e deixar definido as responsabilidades.
  • Selecione a imagem base correta Escolha uma imagem pequena e local confiável (Docker Hub, Verified Publisher, Docker Sponsored Open Source)
  • Reconstrua (rebuild) suas imagens com frequência As imagens são imutáveis. Ao fazer um build, tiramos um “snapshot” daquele momento, portanto, qualquer alteração subsequente necessita de um novo build na imagem.
  • Podemos usar um arquivo .dockerignore Podemos inserir arquivos não relevantes para o build aqui.
  • Desaccople as aplicações Cada container deve ter apenas uma responsabilidade
  • Organize argumentos multi-linhas É possível separar os argumentos em múltiplas linhas

Exemplo de organização dos argumentos em múltiplas linhas:

RUN npm install -g \
  typescript \
  eslint \
  nodemon \
  jest \
  pm2 \
  && npm cache clean --force
Enter fullscreen mode Exit fullscreen mode

Fontes:

Top comments (0)