Skip to content

Latest commit

 

History

History
746 lines (636 loc) · 15.2 KB

File metadata and controls

746 lines (636 loc) · 15.2 KB

Guia de Deploy - Varion

🚀 Deploy em Produção

Este guia abrange todas as estratégias e configurações para deploy do Varion em diferentes ambientes de produção.

🎯 Estratégias de Deploy

1. Docker Compose (Recomendado)

Ideal para servidores VPS, dedicados ou ambientes containerizados.

2. Kubernetes

Para ambientes empresariais com alta disponibilidade.

3. Serverless

Para aplicações com tráfego variável (Vercel + Railway).

4. Cloud Providers

AWS, GCP, Azure com serviços gerenciados.

🐳 Deploy com Docker Compose

Estrutura de Produção

production/
├── docker-compose.prod.yml
├── nginx/
│   ├── nginx.conf
│   └── ssl/
├── .env.prod
└── backup/
    └── scripts/

1. Configuração do Servidor

# Atualizar sistema
sudo apt update && sudo apt upgrade -y

# Instalar Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Instalar Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Criar usuário para a aplicação
sudo useradd -m -s /bin/bash varion
sudo usermod -aG docker varion

2. Configuração de Ambiente

# Criar estrutura de diretórios
sudo mkdir -p /opt/varion/{app,data,logs,backups}
sudo chown -R varion:varion /opt/varion

# Clonar repositório
cd /opt/varion/app
git clone <repository-url> .

# Configurar variáveis de ambiente
cp .env.example .env.prod

3. Arquivo docker-compose.prod.yml

version: '3.8'

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
      target: production
    container_name: varion-frontend-prod
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - NEXT_PUBLIC_API_URL=https://api.yourdomain.com
    networks:
      - varion-network

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: production
    container_name: varion-backend-prod
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/varion_prod
      - JWT_SECRET=${JWT_SECRET}
      - CORS_ORIGIN=https://yourdomain.com
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - varion-network

  postgres:
    image: postgres:15-alpine
    container_name: varion-postgres-prod
    restart: unless-stopped
    environment:
      - POSTGRES_DB=varion_prod
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./backend/scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - varion-network

  nginx:
    image: nginx:alpine
    container_name: varion-nginx-prod
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - ./logs/nginx:/var/log/nginx
    depends_on:
      - frontend
      - backend
    networks:
      - varion-network

volumes:
  postgres_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /opt/varion/data/postgres

networks:
  varion-network:
    driver: bridge

4. Configuração Nginx

# nginx/nginx.conf
events {
    worker_connections 1024;
}

http {
    upstream frontend {
        server frontend:3000;
    }

    upstream backend {
        server backend:3001;
    }

    # Redirect HTTP to HTTPS
    server {
        listen 80;
        server_name yourdomain.com www.yourdomain.com;
        return 301 https://$server_name$request_uri;
    }

    # HTTPS Frontend
    server {
        listen 443 ssl http2;
        server_name yourdomain.com www.yourdomain.com;

        ssl_certificate /etc/nginx/ssl/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/privkey.pem;

        location / {
            proxy_pass http://frontend;
            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;
        }
    }

    # HTTPS Backend API
    server {
        listen 443 ssl http2;
        server_name api.yourdomain.com;

        ssl_certificate /etc/nginx/ssl/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/privkey.pem;

        location / {
            proxy_pass http://backend;
            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;
        }
    }
}

5. Deploy Script

#!/bin/bash
# scripts/deploy.sh

set -e

echo "🚀 Iniciando deploy do Varion..."

# Backup do banco antes do deploy
./scripts/backup-db.sh

# Pull das últimas mudanças
git pull origin main

# Build e deploy
docker-compose -f docker-compose.prod.yml down
docker-compose -f docker-compose.prod.yml up --build -d

# Executar migrations
docker-compose -f docker-compose.prod.yml exec backend pnpm migration:run

# Verificar saúde dos serviços
sleep 10
./scripts/health-check.sh

echo "✅ Deploy concluído com sucesso!"

☸️ Deploy com Kubernetes

1. Manifests Kubernetes

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: varion

---
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: varion-config
  namespace: varion
data:
  NODE_ENV: "production"
  POSTGRES_DB: "varion_prod"

---
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: varion-secrets
  namespace: varion
type: Opaque
data:
  DB_PASSWORD: <base64-encoded-password>
  JWT_SECRET: <base64-encoded-jwt-secret>

---
# k8s/postgres.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: varion
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:15-alpine
        env:
        - name: POSTGRES_DB
          valueFrom:
            configMapKeyRef:
              name: varion-config
              key: POSTGRES_DB
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: varion-secrets
              key: DB_PASSWORD
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: postgres-storage
          mountPath: /var/lib/postgresql/data
      volumes:
      - name: postgres-storage
        persistentVolumeClaim:
          claimName: postgres-pvc

---
# k8s/backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: varion
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: varion/backend:latest
        env:
        - name: NODE_ENV
          valueFrom:
            configMapKeyRef:
              name: varion-config
              key: NODE_ENV
        - name: DATABASE_URL
          value: "postgresql://postgres:$(DB_PASSWORD)@postgres:5432/varion_prod"
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: varion-secrets
              key: DB_PASSWORD
        ports:
        - containerPort: 3001

---
# k8s/frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: varion
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: varion/frontend:latest
        env:
        - name: NODE_ENV
          valueFrom:
            configMapKeyRef:
              name: varion-config
              key: NODE_ENV
        - name: NEXT_PUBLIC_API_URL
          value: "https://api.yourdomain.com"
        ports:
        - containerPort: 3000

---
# k8s/services.yaml
apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: varion
spec:
  selector:
    app: postgres
  ports:
  - port: 5432
    targetPort: 5432

---
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: varion
spec:
  selector:
    app: backend
  ports:
  - port: 3001
    targetPort: 3001

---
apiVersion: v1
kind: Service
metadata:
  name: frontend
  namespace: varion
spec:
  selector:
    app: frontend
  ports:
  - port: 3000
    targetPort: 3000

---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: varion-ingress
  namespace: varion
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - yourdomain.com
    - api.yourdomain.com
    secretName: varion-tls
  rules:
  - host: yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 3000
  - host: api.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: backend
            port:
              number: 3001

2. Deploy Kubernetes

# Aplicar manifests
kubectl apply -f k8s/

# Verificar status
kubectl get pods -n varion
kubectl get services -n varion
kubectl get ingress -n varion

# Logs
kubectl logs -f deployment/backend -n varion
kubectl logs -f deployment/frontend -n varion

🌐 Deploy Serverless

1. Frontend (Vercel)

// vercel.json
{
  "buildCommand": "pnpm build",
  "outputDirectory": ".next",
  "framework": "nextjs",
  "env": {
    "NEXT_PUBLIC_API_URL": "https://api.yourdomain.com"
  },
  "regions": ["cle1", "gru1"]
}
# Deploy
npx vercel --prod

# Configurar domínio customizado
npx vercel domains add yourdomain.com

2. Backend (Railway/Heroku)

# railway.toml
[build]
builder = "nixpacks"
buildCommand = "pnpm build"

[deploy]
startCommand = "pnpm start"
restartPolicyType = "always"

[[services]]
name = "varion-backend"

[services.env]
NODE_ENV = "production"
PORT = { default = 3001 }

🔧 Configurações de Produção

1. Variáveis de Ambiente

# .env.prod
NODE_ENV=production

# Database
DATABASE_URL=postgresql://user:password@host:5432/varion_prod
DB_HOST=postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=strong_password_here
DB_NAME=varion_prod

# Authentication
JWT_SECRET=very_strong_jwt_secret_key_256_bits
JWT_EXPIRES_IN=7d

# CORS
CORS_ORIGIN=https://yourdomain.com

# API
API_PORT=3001
API_PREFIX=/api

# Logs
LOG_LEVEL=info
LOG_FILE=/var/log/varion/app.log

# Frontend
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
NEXT_PUBLIC_APP_NAME=Varion

2. Otimizações de Performance

# backend/Dockerfile (multi-stage)
FROM node:18-alpine AS base
RUN corepack enable pnpm

FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod

FROM base AS build
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

FROM base AS production
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nodejs
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/package.json ./package.json
USER nodejs
EXPOSE 3001
CMD ["node", "dist/server.js"]

3. Configuração de Banco

-- Configurações de produção PostgreSQL
-- postgresql.conf
shared_preload_libraries = 'pg_stat_statements'
max_connections = 200
shared_buffers = 256MB
effective_cache_size = 1GB
maintenance_work_mem = 128MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 4MB
min_wal_size = 1GB
max_wal_size = 4GB

📊 Monitoramento

1. Health Checks

#!/bin/bash
# scripts/health-check.sh

echo "🔍 Verificando saúde dos serviços..."

# Frontend
if curl -f http://localhost:3000 > /dev/null 2>&1; then
    echo "✅ Frontend: OK"
else
    echo "❌ Frontend: FALHA"
    exit 1
fi

# Backend
if curl -f http://localhost:3001/api/health > /dev/null 2>&1; then
    echo "✅ Backend: OK"
else
    echo "❌ Backend: FALHA"
    exit 1
fi

# Database
if docker-compose exec postgres pg_isready -U postgres > /dev/null 2>&1; then
    echo "✅ Database: OK"
else
    echo "❌ Database: FALHA"
    exit 1
fi

echo "🎉 Todos os serviços estão funcionando!"

2. Logs Centralizados

# docker-compose.prod.yml (logging)
x-logging: &default-logging
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

services:
  frontend:
    # ...existing config...
    logging: *default-logging

  backend:
    # ...existing config...
    logging: *default-logging

3. Backup Automático

#!/bin/bash
# scripts/backup-db.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/opt/varion/backups"
BACKUP_FILE="$BACKUP_DIR/varion_backup_$DATE.sql"

echo "📁 Criando backup do banco de dados..."

docker-compose exec postgres pg_dump -U postgres varion_prod > $BACKUP_FILE

if [ $? -eq 0 ]; then
    echo "✅ Backup criado: $BACKUP_FILE"

    # Comprimir backup
    gzip $BACKUP_FILE

    # Manter apenas os últimos 7 backups
    find $BACKUP_DIR -name "varion_backup_*.sql.gz" -mtime +7 -delete

    echo "🗂️ Backups antigos removidos"
else
    echo "❌ Falha no backup"
    exit 1
fi

🚨 Rollback

Estratégia de Rollback

#!/bin/bash
# scripts/rollback.sh

PREVIOUS_VERSION=$1

if [ -z "$PREVIOUS_VERSION" ]; then
    echo "❌ Versão anterior não especificada"
    echo "Uso: ./rollback.sh <git-commit-hash>"
    exit 1
fi

echo "🔄 Iniciando rollback para: $PREVIOUS_VERSION"

# Backup atual
./scripts/backup-db.sh

# Checkout da versão anterior
git checkout $PREVIOUS_VERSION

# Deploy da versão anterior
docker-compose -f docker-compose.prod.yml down
docker-compose -f docker-compose.prod.yml up --build -d

echo "✅ Rollback concluído"

📋 Checklist de Deploy

Pré-Deploy

  • Testes unitários passando
  • Testes de integração passando
  • Build de produção sem erros
  • Variáveis de ambiente configuradas
  • SSL/TLS configurado
  • Backup do banco atual

Deploy

  • Aplicação em manutenção (se necessário)
  • Deploy da nova versão
  • Migrations executadas
  • Verificação de saúde dos serviços
  • Testes de fumaça

Pós-Deploy

  • Monitoramento ativo
  • Logs sendo coletados
  • Métricas normais
  • Funcionalidades críticas testadas
  • Aplicação fora de manutenção

🔗 Links Úteis