1
ScoreOdonto Deploy
ruicesar edited this page 2026-05-17 08:16:08 +02:00

🚀 Deploy ScoreOdonto — Guia Completo (VPS 4 → VPS 1)

Este documento detalha o processo de deploy contínuo do ScoreOdonto e o sistema de versionamento automático.


🔁 Visão Geral do Pipeline

Developer (VPS 4)
    └─► git push origin main
            └─► Gitea Webhook → POST http://10.99.0.4:9002/webhook?token=...
                    └─► listener-scoreodonto.js (porta 9002, VPS 4)
                            └─► deploy-prod-scoreodonto.sh
                                    ├─► git pull (VPS 4)
                                    ├─► rsync → VPS 1 (10.99.0.1)
                                    └─► ssh VPS 1 → docker compose up -d --build
                                                        └─► update-version.js (auto-bump patch)
                                                        └─► vite build → nginx:alpine

📦 Versionamento do Sistema

Arquivo de versão

frontend/constants.ts
export const APP_VERSION = 'V1.0.6';

Como funciona o auto-incremento

A cada docker compose up -d --build, o script update-version.js (na raiz do projeto) é chamado automaticamente pelo comando de build do frontend:

// frontend/package.json
"scripts": {
  "build": "node ../update-version.js && vite build"
}

O script incrementa o patch (terceiro número) da versão:

  • V1.0.5V1.0.6V1.0.7 → ...

Warning

O incremento ocorre dentro do container Docker durante o build. Os arquivos no repositório Git não são modificados automaticamente. A nova versão aparece na interface em produção, mas o constants.ts no Git permanece com o valor anterior ao build.

Tabela de tipos de versão

Tipo Exemplo Quando usar Como fazer
Patch (automático) V1.0.5 → V1.0.6 Cada deploy/build Automático — update-version.js cuida
Minor (manual) V1.0.x → V1.1.0 Nova feature significativa ou sprint Editar constants.ts, zerar patch, commitar
Major (manual) V1.x.x → V2.0.0 Rewrite, mudança arquitetural grande Editar constants.ts, zerar minor e patch, commitar

Bumpar versão Minor ou Major manualmente

# 1. Editar o arquivo diretamente
nano /home/deploy/stack/scoreodonto.com/frontend/constants.ts
# Alterar: export const APP_VERSION = 'V1.1.0';

# 2. Commitar
cd /home/deploy/stack/scoreodonto.com
git add frontend/constants.ts
git commit -m "chore(version): bump para V1.1.0"
git push origin main
# → webhook dispara o deploy automaticamente

🤖 Webhook — Configuração

Parâmetro Valor
URL http://10.99.0.4:9002/webhook?token=scoreodonto_deploy_token_9002
Método POST
Eventos Push na branch main
Listener /home/deploy/instrucoes/scoreodonto/listener-scoreodonto.js
Deploy script /home/deploy/instrucoes/scoreodonto/deploy-prod-scoreodonto.sh

Verificar se o listener está ativo

ps aux | grep listener-scoreodonto
# Deve aparecer: node /home/deploy/instrucoes/scoreodonto/listener-scoreodonto.js

Reiniciar o listener (se parou)

pkill -f listener-scoreodonto || true
nohup node /home/deploy/instrucoes/scoreodonto/listener-scoreodonto.js \
  > /tmp/scoreodonto-webhook.log 2>&1 &
echo $! > /tmp/scoreodonto-webhook.pid

🛠️ Deploy Manual (sem webhook)

Use quando o webhook não está disponível ou para forçar um rebuild imediato:

# Na VPS 4
bash /home/deploy/instrucoes/scoreodonto/deploy-prod-scoreodonto.sh

O script executa:

  1. git pull origin main — garante código atualizado na VPS 4
  2. rsync — sincroniza arquivos para VPS 1 (10.99.0.1), excluindo node_modules, .env e .git
  3. docker compose up -d --build — reconstrói e reinicia os containers na VPS 1

🐳 Arquitetura Docker (Produção)

Frontend

Dockerfile: frontend/Dockerfile
Build context: . (raiz do projeto)
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY update-version.js .          # ← script de versionamento vem da raiz
COPY frontend/package*.json frontend/
WORKDIR /app/frontend
RUN npm install
COPY frontend/ .
RUN npm run build                  # → chama update-version.js + vite build

# Stage 2: Serve
FROM nginx:alpine
COPY --from=builder /app/frontend/dist /usr/share/nginx/html
EXPOSE 3013

Backend

Dockerfile: backend/Dockerfile
Porta: 8018
Runtime: Node.js 20

Nginx (Proxy)

Porta externa: 8020
Traefik labels: scoreodonto.com / www.scoreodonto.com → HTTPS (Let's Encrypt)

🔍 Verificação Pós-Deploy

# 1. Checar containers na VPS 1
ssh deploy@10.99.0.1 "docker ps | grep scoreodonto"

# 2. Checar versão em produção
curl -s https://scoreodonto.com | grep -o 'V[0-9]*\.[0-9]*\.[0-9]*' | head -1

# 3. Ver logs do último build
ssh deploy@10.99.0.1 "docker logs scoreodontocom-scoreodonto-frontend-1 --tail 30"

# 4. Ver logs do backend
ssh deploy@10.99.0.1 "docker logs scoreodontocom-scoreodonto-backend-1 --tail 30"

⚠️ Troubleshooting

Problema Diagnóstico Solução
Webhook não dispara `ps aux grep listener`
Versão não atualiza na UI Versão incrementa no container, não no git Normal — a versão no git é a base; o build incrementa
rsync falha ssh deploy@10.99.0.1 echo ok Checar chave SSH e VPN WireGuard
Docker build falha docker logs na VPS 1 Ver logs do container; checar npm install
Frontend em branco nginx config / dist vazia Verificar se vite build completou sem erro
nginx não sobe, porta 8020 ocupada sudo ss -tlnp | grep 8020 Ver seção abaixo — docker-proxy zumbi

🔒 Alerta de Segurança — Docker Duplo (Rootless + Root)

Caution

A VPS 1 usa Docker Rootless. O daemon root (docker.service) está desabilitado intencionalmente. Nunca o reative.

Por que o daemon root é perigoso aqui

O usuário deploy tem acesso sudo. Se o docker.service (root) estiver ativo e deploy estiver no grupo docker, qualquer docker compose up sem DOCKER_HOST cria containers como root — paralelos aos rootless, invisíveis ao docker ps normal, e inacessíveis ao Traefik (que monitora a rede rootless).

Sintoma: porta 8020 ocupada após docker rm -f

Quando um container nginx é force-removed enquanto o daemon root está ativo, o processo docker-proxy root pode ficar preso na porta:

# Diagnóstico
sudo ss -tlnp | grep 8020
# Se aparecer docker-proxy com PID root → daemon root estava ativo

# Solução de emergência
sudo kill <PID do docker-proxy>
cd ~/stack/scoreodonto.com
DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock docker compose rm -sf nginx
DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock docker compose up -d nginx

Estado correto da VPS 1

# Verificar que o daemon root está morto
sudo systemctl status docker        # deve mostrar: inactive (dead)

# Verificar que deploy não está no grupo docker
groups deploy                       # não deve conter "docker"

# Verificar que rootless está respondendo
DOCKER_HOST=unix:///run/user/1000/docker.sock docker ps | grep scoreodonto

📌 Comandos Git Rápidos (fluxo diário)

cd /home/deploy/stack/scoreodonto.com

# Ver estado
git status

# Commitar e enviar (dispara deploy automaticamente)
git add -p                          # adicionar seletivamente
git commit -m "feat: descrição"     # mensagem em português
git push origin main                # → webhook → deploy automático

Tip

Quando trabalhando com Claude Code (worktrees), o merge para main acontece ao final da sessão. O push para main é quem efetivamente dispara o deploy — não o commit em si.