Migração antes da troca do container
Desde a v2.174.0, o .deploy.yml aceita release:: um comando que roda
depois de a imagem estar pronta e antes de o container novo subir. O uso comum
é a migração do banco.
Se o comando falha, o deploy aborta e o container que está no ar não é tocado.
Exemplo: Prisma
O Dockerfile tem um estágio builder com o CLI do Prisma e o schema. O estágio
final da imagem não precisa levar essas dependências.
project: crm
system: sys
type: docker-build
port: 3000
build:
context: .
dockerfile: Dockerfile
target: runtime # estágio final, o que sobe em produção
release:
target: builder # estágio com o CLI do Prisma
command: ["npx", "prisma", "migrate", "deploy"]
retries: 4
retry_delay: 10s
timeout: 10m
environment:
DATABASE_URL: "{{::DATABASE_URL}}"Aqui o build.target escolhe o estágio da app e o release.target escolhe o
estágio da migração. O runner builda o segundo como crm:<versão>-release,
roda o comando e apaga a imagem no fim, com sucesso ou falha.
O que o runner faz
- Builda ou puxa a imagem da app.
- Roda o
release:numdocker run --rm, com o mesmo env e secrets da instância, as mesmas redes e o mesmohosts:da app. Sem labels do Traefik. - Só então sobe o candidato e faz a troca.
O log ganha a fase [5/8] RELEASE. Sem release: a numeração segue [n/7].
command aceita lista (exec direto) ou string (vira sh -c). Prefira a lista:
não passa por shell.
Retentativa
retries: 4 são quatro tentativas depois da primeira, cinco no total, com
retry_delay entre elas. Serve para o banco que ainda está subindo ou para um
lock de migração. timeout vale por tentativa: estourou, o runner mata o
container (docker kill) e conta a tentativa. Os padrões são retries: 0,
retry_delay: 10s e timeout: 10m.
Quando falha
Depois da última tentativa o deploy termina com:
release_falhou: exit 1 depois de 5 tentativas — <últimas 20 linhas do stderr>- O container no ar continua o mesmo, na versão anterior. O symlink
currenté devolvido. - O diagnóstico e a notificação saem com a fase
release. - O stderr e o comando logado passam pela máscara de segredos: os valores do env
da app e os tokens por padrão. Isso inclui valores que não são segredo, como
production.
Uma migração que falhou no meio pode ter aplicado parte das mudanças. O runner não desfaz isso.
Rollback
runner rollback não roda o release. Ele volta a imagem, não o banco. Se a
versão anterior não funciona com o schema novo, a migração reversa é decisão
sua.
Um runner deploy <app> --force da mesma versão roda o release de novo. Escreva
a migração para ser idempotente (o prisma migrate deploy já é).
Por instância
instances:
staging:
release:
retries: 1O campo declarado na instância substitui o do app e o ausente herda.
Limitações
- O container de release não monta os
volumes:da app. Emimage_mode: bind-mount, o código montado em/appnão existe lá. target:exigebuild:. Comimage_mode: prebuiltou sourceregistry, o manifesto é recusado comrelease_target_sem_build; userelease:semtarget, que roda na imagem do deploy.- Com
healthcheck.mode: exito release não roda: não há troca de container. - A migração ocupa uma thread do runner durante a execução, até o
timeout.
Veja também a referência do `.deploy.yml`.