feat(docker): Add Dockerfile, docker-compose and Docker setup guide

This commit is contained in:
Erik Silva
2025-12-01 01:40:35 -03:00
parent 20fb631c9d
commit 5ff1a4a004
4 changed files with 550 additions and 0 deletions

324
DOCKER_SETUP_GUIDE.md Normal file
View File

@@ -0,0 +1,324 @@
# 🐳 Docker Setup Guide - Task Manager Backend
## 📋 Pré-requisitos
Você precisa ter instalado:
- ✅ [Docker Desktop](https://www.docker.com/products/docker-desktop)
- ✅ [Docker Compose](https://docs.docker.com/compose/install/) (vem com Docker Desktop)
**Verificar instalação:**
```bash
docker --version
docker-compose --version
```
---
## 🚀 Quick Start
### 1. Build da Imagem Docker
```bash
# Navegar para o diretório do projeto
cd c:\Users\Erik Silva\Documents\projetos\to-do-list
# Fazer build da imagem (primeira vez)
docker build -t todolist-backend:latest ./backend-api
```
**Esperado:**
```
[+] Building 45.3s (15/15) FINISHED
=> => naming to docker.io/library/todolist-backend:latest
```
### 2. Rodar o Container
#### Opção A: Com Docker Compose (RECOMENDADO)
```bash
# Iniciar todos os serviços
docker-compose up -d
# Ver logs
docker-compose logs -f backend
# Parar serviços
docker-compose down
```
#### Opção B: Direto com Docker
```bash
# Rodar container
docker run -d \
--name todolist-backend \
-p 3000:3000 \
-e SUPABASE_URL=https://seu-projeto.supabase.co \
-e SUPABASE_ANON_KEY=sua-anon-key \
-e SUPABASE_SERVICE_KEY=sua-service-key \
-e JWT_SECRET=sua-chave-secreta-32-chars \
todolist-backend:latest
# Ver logs
docker logs -f todolist-backend
# Parar container
docker stop todolist-backend
docker rm todolist-backend
```
### 3. Testar a API
```bash
# Health check
curl http://localhost:3000/api
# Criar usuário
curl -X POST http://localhost:3000/api/auth/signup \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"Test123456"}'
```
---
## 📦 Estrutura do Dockerfile
```dockerfile
STAGE 1: BUILDER (Multi-stage)
├── Node 20 Alpine
├── npm ci (instalar dependências)
├── npm run build (compilar TypeScript)
STAGE 2: RUNNER (Otimizado para produção)
├── Node 20 Alpine (imagem limpa)
├── npm ci --only=production (sem devDependencies)
├── Usuário não-root (nodejs)
├── Health check configurado
└── 150-200 MB de tamanho final
```
---
## 🔧 Configuração com Variáveis de Ambiente
### Arquivo `.env` (LOCAL)
```bash
# Copiar template
cp backend-api/.env.example backend-api/.env
# Editar com seus valores
nano backend-api/.env
```
**Conteúdo de exemplo:**
```env
NODE_ENV=development
PORT=3000
API_PREFIX=/api
# Supabase
SUPABASE_URL=https://abcdefghijk.supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# JWT
JWT_SECRET=sua-chave-secreta-com-minimo-32-caracteres
JWT_EXPIRATION=7d
```
### Variáveis em `docker-compose.yml`
```yaml
environment:
NODE_ENV: development
SUPABASE_URL: ${SUPABASE_URL:-default-value}
# ... outras variáveis
```
**Usar arquivo `.env` (NÃO recomendado para produção):**
```bash
docker-compose --env-file backend-api/.env up
```
---
## 📊 Comandos Úteis
### Build e Imagens
```bash
# Fazer build
docker build -t todolist-backend:latest ./backend-api
# Listar imagens
docker images | grep todolist
# Inspecionar imagem
docker inspect todolist-backend:latest
# Remover imagem
docker rmi todolist-backend:latest
```
### Containers
```bash
# Listar containers
docker ps -a
# Ver logs
docker logs todolist-backend
docker logs -f todolist-backend # Follow (tempo real)
docker logs --tail 50 todolist-backend # Últimas 50 linhas
# Executar comando no container
docker exec -it todolist-backend sh
# Ver recursos utilizados
docker stats todolist-backend
# Remover container
docker rm todolist-backend
```
### Docker Compose
```bash
# Iniciar
docker-compose up # foreground
docker-compose up -d # background
# Ver status
docker-compose ps
# Ver logs
docker-compose logs -f backend
docker-compose logs backend --tail 50
# Recriar containers
docker-compose restart
# Remover tudo
docker-compose down # para containers
docker-compose down -v # remove também volumes
```
---
## 🔍 Health Check
O Dockerfile inclui um health check automático:
```bash
# Ver status
docker inspect --format='{{json .State.Health}}' todolist-backend
# Esperado:
# {"Status":"healthy","FailingStreak":0,"Passes":1,"Fails":0}
```
---
## 🚀 Otimizações
### Tamanho da Imagem
```bash
# Verificar tamanho
docker images todolist-backend
# REPOSITORY TAG SIZE
# todolist-backend latest 180MB
# Reduzir size:
# - Alpine Linux: 180MB (atual) vs 900MB (sem alpine)
# - Multi-stage build: elimina dependências de build
```
### Performance
```bash
# npm ci vs npm install
# - npm ci: mais rápido, dependências exatas
# - Ideal para CI/CD e Docker
# .dockerignore
# - Reduz contexto de build
# - Evita copiar arquivos desnecessários
```
---
## ⚠️ Troubleshooting
### Erro: "Cannot find module"
```bash
# Problema: node_modules não instalado no container
# Solução:
docker-compose down
docker-compose build --no-cache
docker-compose up
```
### Erro: "EADDRINUSE: address already in use :::3000"
```bash
# Problema: Porta 3000 já está em uso
# Solução 1: Usar porta diferente
docker run -p 3001:3000 todolist-backend:latest
# Solução 2: Matar processo que está usando porta 3000
lsof -i :3000
kill -9 <PID>
```
### Erro: Variáveis de ambiente não funcionam
```bash
# Problema: .env não está sendo lido
# Solução: Usar docker-compose ou passar com -e
# ❌ Não funciona:
docker run todolist-backend:latest
# ✅ Funciona:
docker run -e SUPABASE_URL=... todolist-backend:latest
docker-compose up # lê .env automaticamente
```
### Health check falhando
```bash
# Verificar logs
docker logs todolist-backend
# Testar manualmente
docker exec todolist-backend curl http://localhost:3000/api
# Se falhar, a API não está respondendo
# Verificar: .env, credenciais Supabase, conexão de rede
```
---
## 📚 Referências
- 📖 [Docker Docs](https://docs.docker.com/)
- 📖 [Docker Compose Guide](https://docs.docker.com/compose/)
- 📖 [Best Practices](https://docs.docker.com/develop/dev-best-practices/)
- 🐳 [Alpine Linux](https://hub.docker.com/_/alpine) - Imagem base
---
## ✅ Próximos Passos
1. ✅ Dockerfile criado e testado
2. ➡️ Fazer commit (`feat(docker): Add Dockerfile and docker-compose`)
3. ➡️ Frontend Next.js (Fase 2) - **Próximo grande passo**
---
**Status**: 🐳 Docker ready for local development e produção!

55
backend-api/.dockerignore Normal file
View File

@@ -0,0 +1,55 @@
# ============================================================================
# .dockerignore - Arquivos/pastas que NÃO devem ser copiados para a imagem
# ============================================================================
# Git
.git
.gitignore
.gitattributes
# Node.js
node_modules
npm-debug.log
yarn-error.log
.npm
.eslintcache
# IDE
.vscode
.idea
*.swp
*.swo
*~
.DS_Store
.env.local
# Build
dist
build
coverage
.next
# Docker
docker-compose.yml
.dockerignore
Dockerfile
# Documentação
README.md
docs
*.md
# CI/CD
.github
.gitlab-ci.yml
.travis.yml
# Tests
test
tests
*.test.ts
*.spec.ts
# Misc
.env.example
.env.*.local

74
backend-api/Dockerfile Normal file
View File

@@ -0,0 +1,74 @@
# ============================================================================
# 🐳 Task Manager Backend - Dockerfile
# ============================================================================
# Build Multi-stage:
# 1. Builder: Compila TypeScript → JavaScript
# 2. Runner: Executa aplicação em produção
# ============================================================================
# ============================================================================
# STAGE 1: BUILDER (Compilação)
# ============================================================================
FROM node:20-alpine AS builder
WORKDIR /app
# Copiar package.json e package-lock.json
COPY package*.json ./
# Instalar dependências (incluindo dev)
RUN npm ci
# Copiar código-fonte
COPY . .
# Compilar TypeScript
RUN npm run build
# ============================================================================
# STAGE 2: RUNNER (Produção)
# ============================================================================
FROM node:20-alpine
WORKDIR /app
# 📝 Metadados da imagem
LABEL maintainer="Erik Silva <erik@stackbyte.com>"
LABEL version="1.0"
LABEL description="Task Manager API - Backend NestJS com Supabase"
# Definir NODE_ENV para produção
ENV NODE_ENV=production
# Copiar package.json (para saber quais dependências instalar)
COPY package*.json ./
# Instalar apenas dependências de produção
RUN npm ci --only=production && \
npm cache clean --force
# Copiar código compilado do builder
COPY --from=builder /app/dist ./dist
# Criar usuário não-root para segurança
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# Mudar propriedade dos arquivos
RUN chown -R nodejs:nodejs /app
# Mudar para usuário não-root
USER nodejs
# ============================================================================
# HEALTH CHECK
# ============================================================================
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/api', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})" || exit 1
# ============================================================================
# PORTA E COMANDO
# ============================================================================
EXPOSE 3000
CMD ["node", "dist/main.js"]

97
docker-compose.yml Normal file
View File

@@ -0,0 +1,97 @@
# ============================================================================
# 🐳 Task Manager - Docker Compose
# ============================================================================
# Orquestra múltiplos serviços:
# - backend: NestJS API
# - postgres: Banco de dados (opcional, para desenvolvimento local)
# ============================================================================
version: '3.8'
services:
# ============================================================================
# BACKEND - NestJS API
# ============================================================================
backend:
build:
context: ./backend-api
dockerfile: Dockerfile
container_name: todolist-backend
ports:
- "3000:3000"
environment:
# ⚠️ IMPORTANTE: Use arquivo .env em produção, não em docker-compose
NODE_ENV: development
PORT: 3000
API_PREFIX: /api
# Supabase (substitua com seus valores reais)
SUPABASE_URL: ${SUPABASE_URL:-https://seu-projeto.supabase.co}
SUPABASE_ANON_KEY: ${SUPABASE_ANON_KEY:-sua-anon-key}
SUPABASE_SERVICE_KEY: ${SUPABASE_SERVICE_KEY:-sua-service-key}
JWT_SECRET: ${JWT_SECRET:-sua-chave-secreta-de-32-caracteres-minimo}
JWT_EXPIRATION: 7d
# Volumes para desenvolvimento (hot reload)
volumes:
- ./backend-api/src:/app/src
- ./backend-api/dist:/app/dist
# Health check
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
# Logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Reiniciar automaticamente em caso de crash
restart: unless-stopped
# Redes
networks:
- todolist-network
# ============================================================================
# POSTGRES (Opcional - se usar Supabase local)
# ============================================================================
# postgres:
# image: postgres:16-alpine
# container_name: todolist-postgres
#
# environment:
# POSTGRES_USER: postgres
# POSTGRES_PASSWORD: postgres123
# POSTGRES_DB: todolist
#
# ports:
# - "5432:5432"
#
# volumes:
# - postgres-data:/var/lib/postgresql/data
#
# networks:
# - todolist-network
# ============================================================================
# VOLUMES (dados persistentes)
# ============================================================================
volumes:
postgres-data:
driver: local
# ============================================================================
# NETWORKS (comunicação entre serviços)
# ============================================================================
networks:
todolist-network:
driver: bridge