No mundo do desenvolvimento de software, a entrega contínua de valor é essencial para se manter competitivo. É aqui que entra o CI/CD (Integração Contínua e Entrega Contínua/Implantação Contínua). Este artigo explora a criação de uma pipeline de CI/CD para aplicações Node.js usando Docker e GitHub Actions, oferecendo um guia prático para implementar essas práticas no seu fluxo de trabalho.
Requisitos
Para configurar nosso pipeline, precisaremos das seguintes ferramentas:
- Node.js: Ambiente de execução para JavaScript;
- Docker: Plataforma de contêineres que facilita a criação, envio e execução de aplicações;
- GitHub Actions: Serviço de integração contínua e entrega contínua que permite automatizar fluxos de trabalho diretamente no GitHub;
- Outras ferramentas úteis: ESLint para linting e Jest para testes.
Repositório de exemplo
Para nossa demonstração de hoje, sugerimos que você siga os passos da próxima seção para aprender como baixar e configurar o Node.js na sua máquina local e dockerizar sua aplicação através da criação do Dockerfile. Porém, se você já souber esses passos e quiser um repositório que contém um Dockerfile pronto para ser usado, você pode usar o código que está disponível no repositório https://github.com/toolbox-playground/hello-world-com-docker-languages/tree/main/nodejs, no qual temos um simples “Hello World” feito em Node.js já dockerizado.
Preparando o ambiente
Configuração do Projeto Node.js
Para iniciar, vamos configurar um projeto básico em Node.js. Certifique-se de ter o Node.js instalado em sua máquina.
# Crie o diretório de trabalho
mkdir nodejs-ci-cd
cd nodejs-ci-cd
# Certifique-se de instalar NPM
sudo apt-get install npm # Para instalações em Ubuntu/Linux
brew install npm # E no caso de MacOs
# Inicie o NPM
npm init -y
Resultado:
O comando acima cria uma estrutura básica para um projeto Node.js. Em seguida, adicione as dependências necessárias:
npm install express
npm install --save-dev jest
No arquivo package.json, configure os scripts para iniciar a aplicação e rodar os testes:
"scripts": {
"start": "node index.js",
"test": "jest"
}
O resultado vai ser um package.json parecido com o do screenshot abaixo:
Dockerizando a Aplicação
Para garantir que nossa aplicação possa ser executada de forma consistente em qualquer ambiente, vamos criar um Dockerfile no projeto:
# Usando a imagem oficial do Node.js
FROM node:latest
# Cria o diretório da aplicação
WORKDIR /app
# Copia os arquivos do projeto
COPY package*.json ./
RUN npm install
# Copia o restante do código
COPY . .
# Expõe a porta que a aplicação irá rodar
EXPOSE 3000
# Comando para iniciar a aplicação
CMD ["npm", "start"]
Com o Dockerfile pronto, construa e teste a imagem Docker localmente:
docker build -t nodejs-ci-cd .
docker run -p 3000:8080 nodejs-ci-cd
Você verá algo parecido com a imagem a seguir:
E acessando a nossa aplicação pelo browser, conseguiremos ver a aplicação funcionando:
O próximo passo é o de subir sua imagem Docker em alguma plataforma de container registry, como Docker Hub ou Azure Container Registry, mas como o intuito deste artigo é fazer isso via pipeline CI/CD, vamos deixar esse passo para ser feito no Github actions, na seção a seguir.
Não esqueça de salvar suas alterações localmente e subir para o GitHub seguindo esta documentação.
Configurando o GitHub Actions
O GitHub Actions (https://docs.github.com/pt/actions) é uma plataforma de automação que permite criar workflows customizados diretamente no repositório GitHub. Esses workflows podem ser configurados para executar testes, builds, deploys, entre outras tarefas automatizadas.
Criando o Workflow
Crie um diretório .github/workflows na raiz do seu projeto no GitHub e adicione um arquivo ci-cd.yml com o seguinte conteúdo:
name: CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build Docker image
run: cd nodejs && docker build -t nodejs-ci-cd .
- name: Push Docker image to Docker Hub
env:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
run: |
echo $DOCKER_HUB_PASSWORD | docker login -u $DOCKER_HUB_USERNAME --password-stdin
docker tag nodejs-ci-cd $DOCKER_HUB_USERNAME/nodejs-ci-cd
docker push $DOCKER_HUB_USERNAME/nodejs-ci-cd
Ou se você preferir, ao criar/entrar no seu repositório no GitHub, clique em Actions → New Workflow → Set up a workflow yourself → copie e cole o código yaml acima, conforme mostra o screenshot abaixo:
Não esqueça de adicionar as variáveis contendo usuário e senha do seu Docker Hub, mas evite colocá-las no formato hard-coded, ou seja, usuário e senha fixos no seu arquivo yaml, pois se seu repositório for público, você estará expondo seu usuário e senha do Docker Hub para qualquer pessoa no mundo.
Para configurar variáveis no GitHub, é possível ir em Settings → Secrets and Variables → Actions. Dentro do GitHub existem vários tipos de variáveis, cada um com sua devida utilidade e caso de uso definidos e você pode conferir suas diferenças em clicando aqui.
Esse workflow será acionado em cada push para a branch main, executando os testes, construindo a imagem Docker e publicando-a no Docker Hub.
Você pode logar no seu Docker Hub e ver sua imagem publicada lá.
Agora que concluímos a integração contínua (CI) e nossa imagem está armazenada em um Container Registry, podemos nos concentrar na entrega contínua (CD) da nossa aplicação. O GitHub é um dos serviços de Git que mais contribui com a comunidade, criando várias documentações e formas de engajar as pessoas. Eles disponibilizam muitas documentações que podemos usar para nossos propósitos, que podem ser encontradas em https://docs.github.com/en/actions/deployment/deploying-to-your-cloud-provider/deploying-to-azure. Dessa forma, você pode usar variações desses arquivos, usando-os como base para te ajudar com a criação do CD da sua aplicação.
No nosso caso, como forma de ser objetivo no nosso artigo, vamos simular o deploy da nossa aplicação feita em Node.js em um App Service usando como base o que o GitHub disponibilizou em https://docs.github.com/en/actions/deployment/deploying-to-your-cloud-provider/deploying-to-azure/deploying-docker-to-azure-app-service .
/ ** Continuação da parte que fizemos do CI ** /
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
steps:
- name: Docker Login
env:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
run: |
echo $DOCKER_HUB_PASSWORD | docker login -u $DOCKER_HUB_USERNAME --password-stdin
- name: Deploy to Azure Web App
env:
AZURE_WEBAPP_NAME: MY_WEBAPP_NAME # Nome da Aplicação
id: deploy-to-webapp
uses: azure/webapps-deploy@85270a1854658d167ab239bce43949edb336fa7c
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
images: '$DOCKER_HUB_USERNAME/nodejs-ci-cd:latest'
Implementando o Pipeline
Pipeline de Integração Contínua
A primeira parte do pipeline foca na Integração Contínua, que inclui a instalação das dependências, execução dos testes automatizados e construção da imagem Docker. A execução desses passos garante que cada alteração no código seja verificada imediatamente, permitindo identificar e corrigir erros rapidamente.
Pipeline de Entrega Contínua
A Entrega Contínua envolve o deploy automático da aplicação após a construção bem-sucedida da imagem Docker. Esse deploy pode ser configurado para diferentes ambientes, como staging e produção. Utilizando GitHub Actions, podemos definir diferentes jobs e steps para realizar o deploy em servidores configurados com Docker.
Melhores Práticas
- Segurança: Utilize variáveis de ambiente e segredos (secrets) para armazenar informações sensíveis, como credenciais de login no Docker Hub.
- Monitoramento e Alertas: Implemente ferramentas de monitoramento e configure alertas para ser notificado em caso de falhas no pipeline ou na aplicação em produção.
Acelere sua carreira conosco
A Mentoria Next Level DevOps é um programa de mentoria de 12 meses com encontros semanais ao vivo, com um grupo seleto e restrito, onde estaremos do seu lado para mantê-lo relevante e atualizado no mercado de tecnologia, aprendendo e implementando as melhores práticas e ferramentas de DevOps.
Clique aqui para entrar na prioridade pela melhor oferta de lançamento
Considerações Finais
Implementar um pipeline CI/CD para aplicações Node.js utilizando Docker e GitHub Actions não só melhora a eficiência do desenvolvimento como também aumenta a confiabilidade do software entregue. Ao seguir as melhores práticas e ajustar o pipeline às necessidades específicas do seu projeto, você pode garantir entregas contínuas e de alta qualidade.