📚 Módulo 09: DevOps - Docker, Testes Unitários e CI/CD

Na fase final da nossa jornada corporativa, precisaremos empacotar essa infraestrutura colossal (API NestJS e Frontend Node/Next.js) para a nuvem. Entraremos na seara de automação e engenharia de confiabilidade (SRE) com Docker e GitHub Actions.


🐳 1. Docker Multi-Stage (Backend e Frontend)

O empacotamento Multi-stage é mandatório em ambientes corporativos. O Node.js possui pastas pesadas (como node_modules de desenvolvimento) que nunca devem subir para a imagem final de produção (Stage 2).

A. Dockerfile da API (NestJS Backend)

Crie na pasta raiz do repositório tecloja-backend:

# STAGE 1: Compilação e Geração do Prisma
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
COPY prisma ./prisma/
RUN npm ci
COPY . .
RUN npx prisma generate
RUN npm run build

# STAGE 2: Imagem Magra de Produção
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production

# Copia apenas o manifesto e instala dependências de produção
COPY package*.json ./
RUN npm ci --only=production

# Copia o Prisma e o Build compilado do Stage 1
COPY prisma ./prisma/
COPY --from=builder /app/dist ./dist
RUN npx prisma generate

EXPOSE 3000
CMD ["node", "dist/src/main.js"]

B. Dockerfile do Frontend (Next.js App Router)

Com o Next.js, não usamos Nginx. O Next.js traz seu próprio servidor otimizado. Adicione a propriedade output: 'standalone' no next.config.mjs e crie o Dockerfile abaixo na pasta raiz:

# STAGE 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
# A compilação do Next.js gerará a pasta otimizada .next/standalone
RUN npm run build

# STAGE 2: Produção Standalone
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

# Copia apenas a build Standalone estrita (mínima dependência possível)
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public

EXPOSE 3000
# O arquivo server.js é gerado automaticamente pelo Next standalone
CMD ["node", "server.js"]

🧪 2. Testes Unitários com Jest

A integração de CI precisa de bloqueios. Se um desenvolvedor alterar a regra do Checkout e quebrar o estoque, o deploy precisa ser cancelado!

O Jest já vem acoplado ao NestJS. Rode em seu backend: npm run test

Exemplo de Teste de Validação de Domínio (src/produto/produto.service.spec.ts):

import { Test, TestingModule } from '@nestjs/testing';
import { ProdutoService } from './produto.service';
import { PrismaService } from '../prisma/prisma.service';

describe('ProdutoService', () => {
  let service: ProdutoService;
  let prismaMock = {
    produto: { findMany: jest.fn().mockResolvedValue([{ id: 1, nome: 'Mouse', preco: 50, estoque: 10 }]) },
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [ProdutoService, { provide: PrismaService, useValue: prismaMock }],
    }).compile();

    service = module.get<ProdutoService>(ProdutoService);
  });

  it('deve retornar a lista de produtos com sucesso do repositório', async () => {
    const produtos = await service.findAll();
    expect(produtos).toHaveLength(1);
    expect(produtos[0].nome).toEqual('Mouse');
    expect(prismaMock.produto.findMany).toHaveBeenCalledTimes(1);
  });
});

🚀 3. CI/CD com GitHub Actions

Configuraremos as esteiras automatizadas que realizam o teste de qualidade e acionam o Deploy nas provedoras em nuvem ao ocorrer um push na branch main.

A. CI/CD do Backend NestJS (Deploy na Render.com)

Crie o arquivo .github/workflows/deploy.yml no projeto Backend:

name: CI/CD - NestJS Backend
on:
  push:
    branches: [ main ]

jobs:
  qualidade:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Instalar Node.js
        uses: actions/setup-node@v4
        with: { node-version: 20, cache: 'npm' }
      - run: npm ci
      - name: Executar Testes com Jest
        run: npm run test

  deploy:
    needs: qualidade
    runs-on: ubuntu-latest
    steps:
      - name: Acionar Deploy Automático na Render via Webhook
        run: |
          curl -X POST https://api.render.com/deploy/srv-$?key=$

B. CI/CD do Frontend Next.js (Deploy na Vercel)

A Vercel é a empresa criadora do Next.js. O deploy de código Next.js lá possui performance máxima pois utiliza Edge Networking global. Ao invés do Webhook, podemos utilizar a Action oficial da Vercel para subir o front:

Crie o arquivo .github/workflows/deploy.yml no projeto Frontend:

name: CI/CD - Next.js Frontend
on:
  push:
    branches: [ main ]

jobs:
  deploy-vercel:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Instalar Node.js
        uses: actions/setup-node@v4
        with: { node-version: 20, cache: 'npm' }
      - run: npm ci
      - run: npm run build
      
      - name: Deploy na Vercel
        uses: amondnet/vercel-action@v20
        with:
          vercel-token: $
          vercel-org-id: $
          vercel-project-id: $
          vercel-args: '--prod'

✅ Pré-Requisitos deste Módulo

Antes de finalizar o curso e passar para a avaliação final, certifique-se de que:


🤔 Por que fizemos assim?


🔍 Checkpoint

  1. Sucesso no Jest: Execute npm run test na pasta do backend NestJS e confirme se todos os testes unitários foram validados de forma limpa.
  2. Standalone Gerado: Execute npm run build no frontend Next.js e certifique-se de que o compilador gerou com sucesso o diretório .next/standalone/server.js.
  3. Pipeline Integrada: Valide se os segredos e variáveis do Render/Vercel foram preenchidos nas configurações do GitHub e verifique se as esteiras de deploy rodaram e ficaram verdes após o commit.

⚠️ Erros Comuns

Erro Causa Solução
O container do Next.js standalone finaliza com erro alegando falta de arquivos estáticos ou públicos O Dockerfile não copiou as pastas de assets e de estilos estáticos para o runtime final de execução. Certifique-se de incluir as diretrizes de cópia das pastas .next/static e public no estágio final (runner) do Dockerfile do frontend conforme a especificação do guia.
O deploy da Vercel falha no GitHub Actions acusando falta de ID de organização ou projeto As chaves secretas do escopo da Vercel não foram preenchidas no painel de segredos do repositório no GitHub. Vá nas configurações do repositório no GitHub (Settings -> Secrets and variables -> Actions) e adicione os segredos VERCEL_TOKEN, VERCEL_ORG_ID e VERCEL_PROJECT_ID.
Vazamento de conexões de banco de dados reais nos testes locais com o Jest O teste unitário de serviços tenta se conectar no banco físico (Postgres) em tempo de execução. Garanta o isolamento completo da infraestrutura utilizando mocks (jest.fn().mockResolvedValue(...)) para substituir as chamadas físicas de persistência do PrismaService.

🏆 Checklist de Sucesso Acadêmico

Seus projetos finais corporativos devem atender aos seguintes critérios absolutos:


🏁 Encerramento da Formação Full-Stack Enterprise

Missão cumprida, Arquiteto de Software! A partir de um banco de dados relacional e infraestrutura Node.js/NestJS, construímos uma casca performática de e-commerce blindada em nuvem. As habilidades adquiridas nesta maratona formam exatamente as exigências do mercado profissional internacional. Mantenha os seus servidores limpos e boa sorte nas suas próximas criações de software!


Voltar para o Sumário