Deploy em Produção
Vamos fazer deploy da API em diferentes plataformas.
Preparação
typescript
// src/server.tsimport { app } from './app'; const PORT = process.env.PORT || 3000; const server = app.listen(PORT, () => { console.log(`🚀 Server running on port ${PORT}`);}); // Graceful shutdownconst gracefulShutdown = async (signal: string) => { console.log(`\n${signal} received. Shutting down gracefully...`); server.close(async () => { console.log('HTTP server closed'); // Fecha conexões await prisma.$disconnect(); await redis.quit(); console.log('All connections closed'); process.exit(0); }); // Força encerramento após 30s setTimeout(() => { console.error('Forced shutdown'); process.exit(1); }, 30000);}; process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));process.on('SIGINT', () => gracefulShutdown('SIGINT'));Deploy na Railway
bash
# Instalar CLInpm install -g @railway/cli # Loginrailway login # Novo projetorailway init # Adicionar PostgreSQLrailway add # Deployrailway upjson
// railway.json{ "$schema": "https://railway.app/railway.schema.json", "build": { "builder": "NIXPACKS" }, "deploy": { "startCommand": "npm run start:prod", "healthcheckPath": "/health", "restartPolicyType": "ON_FAILURE" }}Deploy na Render
yaml
# render.yamlservices: - type: web name: ecommerce-api env: node buildCommand: npm ci && npm run build && npx prisma generate startCommand: npm run start:prod healthCheckPath: /health envVars: - key: NODE_ENV value: production - key: DATABASE_URL fromDatabase: name: ecommerce-db property: connectionString databases: - name: ecommerce-db databaseName: ecommerce user: ecommerceDeploy na AWS com ECS
yaml
# task-definition.json{ "family": "ecommerce-api", "networkMode": "awsvpc", "requiresCompatibilities": ["FARGATE"], "cpu": "256", "memory": "512", "executionRoleArn": "arn:aws:iam::xxx:role/ecsTaskExecutionRole", "containerDefinitions": [ { "name": "api", "image": "xxx.dkr.ecr.us-east-1.amazonaws.com/ecommerce:latest", "portMappings": [ { "containerPort": 3000, "protocol": "tcp" } ], "environment": [ { "name": "NODE_ENV", "value": "production" } ], "secrets": [ { "name": "DATABASE_URL", "valueFrom": "arn:aws:secretsmanager:xxx:secret:db-url" } ], "healthCheck": { "command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"], "interval": 30, "timeout": 5, "retries": 3 }, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/ecommerce-api", "awslogs-region": "us-east-1", "awslogs-stream-prefix": "ecs" } } } ]}GitHub Actions CI/CD
yaml
# .github/workflows/deploy.ymlname: Deploy on: push: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - run: npm run lint - run: npm run test deploy: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Deploy to Railway uses: bervProject/railway-deploy@main with: railway_token: ${{ secrets.RAILWAY_TOKEN }} service: ecommerce-apiVariáveis de Ambiente em Produção
bash
# Nunca commitar .env em produção!# Use secrets managers # AWS Secrets Manageraws secretsmanager create-secret \ --name prod/ecommerce/env \ --secret-string file://secrets.json # Railwayrailway variables set DATABASE_URL="..."railway variables set JWT_SECRET="..."Monitoramento com PM2
javascript
// ecosystem.config.jsmodule.exports = { apps: [{ name: 'ecommerce-api', script: 'dist/server.js', instances: 'max', exec_mode: 'cluster', env_production: { NODE_ENV: 'production', }, max_memory_restart: '500M', error_file: './logs/error.log', out_file: './logs/out.log', merge_logs: true, }],};bash
# Startpm2 start ecosystem.config.js --env production # Statuspm2 status # Logspm2 logs # Monitoramentopm2 monitChecklist de Deploy
- ✅ Testes passando
- ✅ Build sem erros
- ✅ Variáveis de ambiente configuradas
- ✅ Migrations executadas
- ✅ Health check funcionando
- ✅ HTTPS configurado
- ✅ Logs configurados
- ✅ Monitoramento ativo
Resumo
- ✅ Graceful shutdown implementado
- ✅ Deploy em Railway, Render e AWS
- ✅ CI/CD com GitHub Actions
- ✅ Gerenciamento de secrets
- ✅ PM2 para produção
Próxima aula: Projeto E-commerce - Parte 1! 🛒