Tema
ADR-004 — Estratégia de Deploy (Script + Docker Compose)
Data: 2026-03
Status: Ativo
Contexto
Precisávamos de uma estratégia de deploy que:
- Funcione em um único servidor VPS
- Injete secrets do Azure Key Vault no momento do build
- Garanta que Traefik sempre receba as labels corretas
- Seja simples de executar sem pipeline CI/CD complexo
Alternativas consideradas
| Alternativa | Motivo de descarte |
|---|---|
| Kubernetes | Over-engineering para um servidor; complexidade operacional alta |
| GitHub Actions + Registry | Registry privado adiciona custo e complexidade; push de imagem para VPS continua sendo necessário |
| Dokku/Coolify | Menos controle sobre o processo de build; difícil injetar secrets de Key Vault |
| Docker Swarm | Similar ao Kubernetes em complexidade para o porte atual |
| Script local + Docker Compose | Controle total, simples, funciona sem infra extra — escolhido |
Decisão
deploy.sh — script shell que orquestra o deploy completo:
- Carrega
AZURE_CLIENT_SECRETde/home/crm/.crm-secrets - Busca
CLERK_PUBLISHABLE_KEYdo Key Vault viadocker execno container backend - Builda imagens localmente com
--no-cachee tag timestamp - Atualiza
.envcom as novas tags de imagem - Sobe containers com os 3 arquivos de compose obrigatórios
- Aguarda health checks
- Verifica que os containers rodando usam as imagens esperadas
- Limpa imagens dangling
3 arquivos compose obrigatórios:
docker-compose.yml— definição basedocker-compose.override.yml— configuração de produção (env, health checks, CPU)docker-compose.labels.yml— labels Traefik (roteamento)
Por que o deploy.sh é obrigatório
A razão principal é a injeção de NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY no build do frontend. Esse valor:
- Fica no Azure Key Vault (não no
.envdo servidor) - Precisa ser passado como
--build-argnodocker build - NÃO está disponível como variável de ambiente simples
Sem o deploy.sh, o docker compose up usaria o valor vazio ou desatualizado → Clerk não funciona → sistema fora do ar.
Histórico de incidentes: Sistema derrubado 4 vezes (04-14, 04-17, 04-20 x2) por uso direto de docker compose up.
Proteção adicional
Um wrapper em /home/crm/bin/docker bloqueia chamadas diretas de docker compose up/restart/recreate nos containers crm-galdix-*. O deploy.sh usa /usr/bin/docker diretamente para contornar o wrapper.
Consequências
Positivas:
- Deploy simples:
bash deploy.shoubash deploy.sh backend - Health checks automáticos — deploy falha se o serviço não sobe
- Verificação de imagem — garante que o container usa a imagem buildada agora
- Limpeza automática de imagens antigas
Negativas:
- Deploy manual — não tem CI/CD automático em push
- Sem rollback automático (requer identificar a imagem anterior manualmente)
- Deploy só funciona de dentro do servidor (sem deploy remoto automatizado)
Referências de implementação
/home/crm/app/deploy.sh/home/crm/app/docker-compose.yml/home/crm/app/docker-compose.override.yml/home/crm/app/docker-compose.labels.yml