- deploy/modelo.md: reescrito. Agora vale para scoreodonto E newwhats (padronizados). Documenta o registry PELA VPN (10.99.0.3:3000 — o proxy HTTPS corta uploads >~45MB em ~60s), o promote via API v2 (buildx não fala HTTP) e a poda de imagens no deploy-prod.sh. Versão anterior em desuso/ (17/jun). - projetos/newwhats.clube67.com/deploy-prod.md: novo delta do motor — host único, build com contexto na raiz (plugins na imagem), banco newwhats_prod + Dragonfly /2 na VPS3, rede soc, JWT do dev, sem migração Prisma no boot, auth do promote pelo docker login do runner, e o sync-config-dev-para-prod.sh como passo separado. O HMR/dev já estava coberto (infra/ambiente-dev.md + delta do scoreodonto); o dev do motor (next start + rsync, NÃO-HMR) já está em ambiente-dev.md do projeto. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.1 KiB
Deploy — Modelo (Build Once → Promote → Deploy)
Situação: como o deploy funciona, em conceito. Estado real verificado em 11/jul/2026. Vale para scoreodonto.com E newwhats.clube67.com (padronizados no mesmo modelo).
Push na main builda uma vez e publica a imagem por commit; a tag vX.Y.Z re-tagueia essa mesma imagem (sem rebuild) e deploya. Produção nunca builda — só executa imagens prontas.
PUSH main (commit C) TAG vX.Y.Z (no commit C)
│ │
▼ ▼
CI: build (1x) CI: promote (SEM build)
publica :C + :latest copia manifest :C → :vX.Y.Z (MESMO digest) + deploy
▼ ▼
registry (Gitea, pela VPN) produção (VPS1): pull :vX.Y.Z + up --no-build + poda
Garantia central: a imagem em produção é byte-idêntica à que foi buildada e testada. A tag é só um rótulo de release sobre um artefato imutável. O promote confere que o digest de :vX.Y.Z é igual ao de :C antes de deployar.
Registry pela VPN (10.99.0.3:3000) — importante
As imagens são publicadas e puxadas pelo endereço 10.99.0.3:3000 (WireGuard), não por git.clube67.com. Motivo: o proxy HTTPS público corta uploads em ~60 s (banda ~0,75 MB/s), então blobs acima de ~45 MB não sobem (o Gitea recebe o corpo truncado e responde 500). Pela VPN não há corte (~2,4 MB/s). O blob do backend do motor tem 175 MB — só passa pela VPN.
- Exige
insecure-registries: ["10.99.0.3:3000"]no daemon Docker do runner (VPS4) e da VPS1. A porta 3000 não é exposta na internet, só pelo túnel —insecureaqui só desliga a exigência de TLS naquele endereço; o tráfego segue cifrado pelo WireGuard. - O promote copia o manifest pela API v2 do registry (
GET+PUT, byte a byte ⇒ mesmo digest). Não usadocker buildx imagetools, que não fala com registry HTTP. - Correção definitiva (pendente, não bloqueia): aumentar os timeouts do proxy da VPS3 (
client_body_timeout/proxy_send_timeout/proxy_read_timeout≥ 900s,client_max_body_size 0) resolveria também clones/downloads externos.
Poda de imagens no deploy
O deploy-prod.sh, ao fim de cada deploy, remove as imagens vX.Y.Z locais além das 2 mais recentes de cada repo (backend/frontend) — a recém-subida e a anterior (rollback). Só toca em tags vX.Y.Z, nunca imagem em uso, e é best-effort (não aborta o deploy). Evita o acúmulo que chegou a dezenas de GB. (O build cache tem limpeza própria: docker builder prune semanal via cron na VPS4 e VPS1.)
- Por que o modelo importa: acaba a recompilação na promoção (que podia gerar imagem diferente da testada) e a colisão de tags.
- Implementações de referência: scoreodonto.com (
v1.0.40) e newwhats.clube67.com (v1.0.2). O delta do motor está em../projetos/newwhats.clube67.com/deploy-prod.md. - Situações relacionadas:
subir-release.md,rollback.md,versionamento.md; infra em../infra/.