Docker e Containers
Docker garante que seu app rode igual em qualquer ambiente.
Dockerfile
dockerfile
# DockerfileFROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./RUN npm ci COPY . .RUN npm run build # Production imageFROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production # Cria usuário não-rootRUN addgroup --system --gid 1001 nodejsRUN adduser --system --uid 1001 api COPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesCOPY --from=builder /app/package*.json ./COPY --from=builder /app/prisma ./prisma # Gera Prisma ClientRUN npx prisma generate USER api EXPOSE 3000 CMD ["node", "dist/server.js"]Docker Compose
yaml
# docker-compose.ymlversion: '3.8' services: api: build: . ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=postgresql://postgres:postgres@db:5432/ecommerce - REDIS_URL=redis://redis:6379 - JWT_SECRET=${JWT_SECRET} depends_on: db: condition: service_healthy redis: condition: service_started restart: unless-stopped db: image: postgres:15-alpine ports: - "5432:5432" environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - POSTGRES_DB=ecommerce volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data command: redis-server --appendonly yes nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./certs:/etc/nginx/certs:ro depends_on: - api volumes: postgres_data: redis_data:Docker Compose para Dev
yaml
# docker-compose.dev.ymlversion: '3.8' services: api: build: context: . dockerfile: Dockerfile.dev ports: - "3000:3000" volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development - DATABASE_URL=postgresql://postgres:postgres@db:5432/ecommerce_dev - REDIS_URL=redis://redis:6379 command: npm run dev db: image: postgres:15-alpine ports: - "5432:5432" environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - POSTGRES_DB=ecommerce_dev redis: image: redis:7-alpine ports: - "6379:6379"dockerfile
# Dockerfile.devFROM node:20-alpine WORKDIR /app COPY package*.json ./RUN npm install COPY . . EXPOSE 3000 CMD ["npm", "run", "dev"]Nginx como Reverse Proxy
nginx
# nginx.confevents { worker_connections 1024;} http { upstream api { server api:3000; } server { listen 80; server_name api.ecommerce.com; location / { proxy_pass http://api; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } }}Comandos Úteis
bash
# Build e startdocker-compose up --build # Backgrounddocker-compose up -d # Logsdocker-compose logs -f api # Executar migrationsdocker-compose exec api npx prisma migrate deploy # Shell no containerdocker-compose exec api sh # Parar tudodocker-compose down # Parar e remover volumesdocker-compose down -v.dockerignore
node_modules
dist
.git
.env
.env.local
*.log
coverage
.nyc_output
Health Check na API
typescript
// src/routes/health.routes.tsimport { Router } from 'express';import { prisma } from '../config/database';import redis from '../config/redis'; const router = Router(); router.get('/health', async (req, res) => { const health = { status: 'ok', timestamp: new Date().toISOString(), services: { database: 'ok', redis: 'ok', }, }; try { await prisma.$queryRaw`SELECT 1`; } catch { health.services.database = 'error'; health.status = 'degraded'; } try { await redis.ping(); } catch { health.services.redis = 'error'; health.status = 'degraded'; } const statusCode = health.status === 'ok' ? 200 : 503; res.status(statusCode).json(health);}); export default router;Resumo
- ✅ Dockerfile multi-stage otimizado
- ✅ Docker Compose para todos os serviços
- ✅ Ambiente de desenvolvimento com hot reload
- ✅ Nginx como reverse proxy
- ✅ Health checks
Próxima aula: Deploy em Produção! 🚀