
Sabe aquele código de aplicação parado no seu repo git?
Você não dá nada para aquela aplicação web ou projeto de estudo (e nós também — rs’), mas já pensou em disponibilizá-la como uma imagem de container Docker?
Pois bem, vamos lá…
Neste exemplo, vamos usar uma aplicação em Nodejs. Mas os conceitos poderão ser aplicados em outros casos.
Repositório com a aplicação:
GitHub – danilomarquesn/hello-nodejs
Passo 1: O Clone

#easteregg
Vamos clonar a aplicação para o nosso diretório de trabalho:
$ git clone git@github.com:danilomarquesn/hello-nodejs.git
Passo 2: Dockerfile
Vamos construir o arquivo de Dockerfile (receita da nossa imagem), mas antes precisamos entender o que é o Dockerfile e como a aplicação funciona, assim como, suas dependências.
Dockerfile: De uma maneira bem simples, pode ser usado para automatizar a criação das suas imagens.
Sabemos que a app foi constuída em Nodejs, logo teremos que garantir que a imagem base atenda a este requisito. No dockerhub, vamos localizar a imagem oficial do Node, para o nosso projeto.
node
Node.js is a JavaScript-based platform for server-side and networking applications.hub.docker.com

Nota: Nós poderíamos utilizar uma imagem linux “pura” e instalar todas a dependências do projeto e depois disponibilizar? SIM. Mas o finalidade aqui não é reinventar a roda ou redescobrir o fogo. Essa abordagem, fará muito mais sentido em contextos onde você precisa ter total controle e saber exatamente tudo o que a imagem contém (no contexto de segurança, por exemplo). Em nosso exemplo, a imagem oficial do Node atende aos requisitos.
Agora que já sabemos a imagem base que iremos utilizar, vamos nos certificar que estamos usando a mesma tag/versão da máquina local em que a app foi desenvolvida.
$ node --version
Retornará algo como: v16.15.1 (a sua versão provavelmente estará diferente)
Após clonar o projeto, vamos acessar a pasta src, para criarmos os arquivos necessários.
$ cd src/
Dockerfile
# indicamos a imagem base + versao, para garantir a idempotencia
FROM node:16.15.1
# diretorio de trabalho, onde estará nossa app dentro do container
WORKDIR /app
# copiamos apenas os arquivos de dependencias do src para o WORKDIR
COPY package*.json ./
# instalamos as dependencias restantes para a app rodar com sucesso
RUN npm install
# copiamos todo o conteúdo do src para o WORKDIR
COPY . .
# expomos nossa app para a porta 3000 do container
EXPOSE 3000
# comando para executar a app (start)
CMD ["node", "server.js"]
Passo 3: Build
# docker build seu_namespace_dockerhub/nome-da-app:versao (v1..v2..latest)
$ docker build -t danilomarques/hello-nodejs:v1
Pulo do gato…

Repare que copiamos apenas os arquivos de dependência da app (package-lock.json e package.json). Após a instalação, copiamos os arquivos restantes, por quê?
Porque queremos aproveitar o conceito de camadas do Docker.
Vamos testar?
Altere o seu Dockerfile para o seguinte modelo:
FROM node:16.15.1
WORKDIR /app
# COPY package*.json ./
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"]
Agora adicione a seguinte linha em qualquer arquivo da sua app. Neste exemplo, vamos alterar o server.js:
// Hello world
Execute novamente o build do Docker:
$ docker build -t seu_namespace_dockerhub/hello-nodejs:v1
Repare que pelo simples fato de ter adicionado um comentário no código da aplicação, o docker build entende que houve alteração nos arquivos copiados, então precisa instalar novamente todas as dependências na imagem do container (atualizar a camada correspondente).
No modelo anterior, o docker só irá refazer a camada de dependências quando houver alteração nos arquivos de dependências (package-lock.json e package.json).
Coisa que só irá “pegar” na utilização do dia a dia… E acredite, cada segundo conta, principalmente em projetos maiores.
#PorqueNaPráticaATeoriaÉDiferente
Passo 4: .dockerignore
Se você já executou a sua app, provavelmente encontrará vários arquivos e diretórios temporários necessários para aquela execução local. Mas esses arquivos e diretórios precisam estar na imagem? Muito provavelmente não. Só deixarão a imagem maior, mais pesada…
Semelhante o .gitignore, vamos criar o .dockerignore para informar tudo o que não precisamos na imagem.
$ vi .dockerignore
Como estamos trabalhando com Nodejs no exemplo, só teremos os conteúdo abaixo para adicionar ao arquivo:
node_modules
Nosso diretório atual ficou assim:

Vamos “buildar” e subir nossa app…
$ docker build -t seu_namespace_dockerhub/hello-nodejs:v1
$ docker run -d -p 3000:3000 seu_namespace_dockerhub/hello-nodejs:v1
Nesta etapa, sua aplicação já deve estar pronta para receber solicitações na porta disponibilizada.
Passo 5: Push
Se você já possui uma conta no Docker Hub e criou a imagem com o seu namespace corretamente, basta dar um “docker push” (assumindo que o seu docker login também esteja correto 😑) para enviar par o hub.
$ docker push seu_namespace_dockerhub/hello-nodejs:v1

Deixe um comentário