runner deploy
Executa o pipeline de deploy completo para uma aplicacao ou todas as apps registradas.
Sintaxe
runner deploy <app>
runner deploy <app> [--version <version>]
runner deploy --allParametros
| Parametro | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
<app> |
string | Sim* | Caminho ou nome do projeto (ex: meu-app ou /data/apps/meu-app) |
--version, -v |
string | Nao | Versao especifica para deploy |
--force, -f |
flag | Nao | Forca redeploy mesmo se versao ja implantada |
--skip-tests |
flag | Nao | Pula testes apos deploy |
--verbose, -V |
flag | Nao | Output detalhado com logs tecnicos |
--all |
flag | Nao | Deploya todas as apps registradas |
--port <N> |
int | Nao | Override de porta (v2.19.0). Persiste no state — re-deploys reusam. |
--no-port |
flag | Nao | Desabilita port mapping (strategy=none) so desta deploy (v2.19.0). |
--insecure |
flag | Nao | Bypass de pre-flight de secrets vazios (v2.19.0, NÃO RECOMENDADO). |
--force-unlock |
flag | Nao | Remove .deploy.lock antes de tentar o deploy (v2.26.4). Use quando stale-detection (PID gone OR > LOCK_MAX_AGE) nao disparou e o deploy ainda diz "Another deploy is in progress". |
--allow-missing-required |
flag | Nao | (v2.32.0+) Bypass do pre-flight de variaveis required: declaradas no manifest. Use apenas em rollouts de emergencia onde voce sabe que o container vai subir com placeholders. |
*Use <app> ou --all, nao ambos.
Exemplos
Deploy Padrao
runner deploy --app /data/apps/usuario_meu-appDeploy por Nome
runner deploy meu-appDeploy de Versao Especifica
runner deploy meu-app --version v1.2.3Deploy para Staging
runner deploy meu-app --instance stagingDeploy sem Testes
runner deploy meu-app --skip-testsDeploy Forcado (Redeploy)
runner deploy meu-app --forceDeploy com Output Detalhado
runner deploy meu-app --verboseDeploy de Todas as Apps
runner deploy --allOverride de Porta (v2.19.0)
# Override permanente (persiste no state — re-deploys reusam)
runner deploy myapp --port 9000
# Sem port mapping (strategy=none, container so na rede docker)
runner deploy myapp --no-port--port N sobrescreve qualquer alocacao sticky existente e persiste em state.network.published_port. Use isso pra "fixar" uma porta que voce quer permanente. As deploys subsequentes (manuais ou via fetch --deploy) vao reusar a mesma porta sem precisar --port de novo.
--no-port desabilita port mapping so desta deploy — nao persiste. Util pra debugging ou pra apps que so precisam estar na rede Docker (sem expor pro host).
Veja `runner ports` pra inspecionar/liberar/realocar portas alocadas.
Pre-flight de secrets vazios (v2.19.0)
Antes do container subir, o runner valida que cada secret declarado em .deploy.yml::secrets: tem valor nao-vazio em .runner/secrets.enc (apos decifrar). Se algum esta vazio, o deploy aborta:
runner deploy middleware-241
# Error: deploy_blocked: secrets declared in .deploy.yml have empty values: ["APP_KEY"]
# Bypass: rerun with --insecure (NOT recommended).
# Or fill the values:
# runner env set <app> --key APP_KEY --secret --value <value>Resolução padrão:
runner env set middleware-241 --key APP_KEY --secret --value "base64:$(openssl rand -base64 32)"
runner deploy middleware-241 # agora passaBypass: runner deploy middleware-241 --insecure (so use conscientemente — geralmente significa que o app vai subir quebrado em runtime).
Resolve o caso onde Laravel /up retornava 200 mesmo com APP_KEY vazio, fazendo o runner declarar deploy bem-sucedido enquanto / retornava 500.
Pre-flight de variáveis obrigatórias (v2.32.0+)
O manifest aceita um campo required: no topo declarando variáveis que devem resolver pra valor não-vazio em .env ou .secrets antes do deploy começar:
required:
- NEXT_PUBLIC_SUPABASE_ANON_KEY
- DB_PASSWORDSe alguma estiver ausente ou vazia, runner deploy bailha fatal antes de tocar Docker:
runner deploy sdr-web
# Error: missing_required: variables required by the manifest are unset or
# empty: NEXT_PUBLIC_SUPABASE_ANON_KEY, DB_PASSWORD.
# Set them with `runner env set <app> <KEY> <VALUE>` (or `--secret -f` for
# secrets), then retry the deploy.Resolução padrão:
runner env set sdr-web NEXT_PUBLIC_SUPABASE_ANON_KEY anon-key-value
runner env set sdr-web DB_PASSWORD --secret -f "s3cr3t"
runner deploy sdr-web # agora passaBypass de emergência: runner deploy sdr-web --allow-missing-required (use apenas quando você sabe que o container vai subir com placeholders e isso é intencional).
Por que existe: o checker fecha o cenário onde Next.js (createSupabaseClient(URL, KEY) no middleware) crasha em startup com chave vazia → toda request 500 → healthcheck r.status<500 falha eternamente. Pré-v2.32.0, o runner ficava ~173s em retry loop antes de rolar back. Agora bailha em <1s.
`runner env validate ` como pre-deploy check
Sem --required na linha de comando, runner env validate cai no required: do manifest automaticamente:
runner env validate sdr-web
# Error: missing_required: ... NEXT_PUBLIC_SUPABASE_ANON_KEY, DB_PASSWORD.Use no seu pipeline CI antes de invocar deploy.
Util apos recovery do servidor. A partir da v2.1.0, o --all faz topological sort
baseado no campo depends_on: do .deploy.yml de cada app. Apps sem dependencias
sao deployadas primeiro; apps cujas dependencias falharam sao automaticamente puladas.
Ciclos de dependencia (a -> b -> a) sao detectados e abortam o --all com mensagem
listando os projetos envolvidos.
# Forca redeploy de todas
runner deploy --all --force
# Com output detalhado
runner deploy --all --verboseOutput do Deploy
Formato Padrao
O deploy exibe progresso com badges indicando cada etapa:
[1/6] [PREPARE] Preparando deploy...
[2/6] [ARTIFACT] Copiando artefatos...
[3/6] [ENV] Gerando ambiente...
[4/6] [SECURITY] Verificando segurança...
[5/6] [CONTAINER] Subindo container de teste...
[6/6] [PROMOTE] Promovendo versao...
═══════════════════════════════════════
✓ DEPLOY CONCLUIDO
App: meu-app/production
Versao: v1.2.0
URL: https://app.meusite.com.br
═══════════════════════════════════════Versao Ja Implantada
Se a versao ja esta implantada:
═══════════════════════════════════════
✓ JA IMPLANTADO
App: meu-app/production
Versao: v1.2.0
Use --force para reimplantar
═══════════════════════════════════════Modo Verbose (-V)
O modo verbose exibe logs tecnicos detalhados:
runner deploy meu-app --verboseInclui:
- Versao do Runner
- Caminho do config
- Logs de nivel INFO
- Detalhes de cada operacao
Pipeline de Deploy
O comando executa as seguintes etapas:
Prepare
- Verifica configuracao (
.deploy.yml) - Extrai versao do projeto
- Cria diretorio de versao
- Verifica configuracao (
Artifacts
- Copia artefatos para diretorio de versao
- Limpa workdir (remove arquivos desnecessarios)
Environment
- Processa templates de ambiente
- Gera
.enve.secrets - Encripta e persiste secrets no repo (se ckey configurada)
Test (Blue-Green)
- Sobe container de teste
- Executa health check
- Executa testes de seguranca
- Executa Playwright (se configurado)
Promote
- Atualiza symlink
current - Gera Traefik dynamic config
- Roteia trafego para nova versao
- Atualiza symlink
Cleanup
- Remove containers de teste
- Remove versoes antigas
Notify
- Envia notificacao (Telegram/Discord)
Comportamento
Rollback Automatico (v1.4.1)
O Runner faz rollback automatico dependendo da fase em que o deploy falha:
| Fase que falha | Impacto | Rollback |
|---|---|---|
| Fetch/Prepare (fases 0-1) | Container antigo nao foi tocado | Nenhum necessario — versao anterior continua ativa |
| Build (fase 3) | Container antigo nao foi tocado | Nenhum necessario — versao anterior continua ativa |
| Start (fase 4) com portas | Container antigo foi parado | Automatico — container anterior reiniciado |
| Start (fase 4) com Traefik | Container antigo nao foi tocado | Nenhum necessario — trafego continua na versao anterior |
| Health check (fase 5) | Container novo subiu mas nao e saudavel | Automatico — novo container removido, anterior reiniciado |
Em todos os casos, a notificacao de falha indica qual versao ficou ativa.
Cleanup do container quebrado (v2.26.4+)
Quando o Start da fase 4 falha sem versao anterior pra rollback (first deploy), o runner agora remove o container quebrado antes de retornar erro. Pre-v2.26.4, ele ficava UP segurando portas — bloqueava docker compose up paralelo com Bind for 0.0.0.0:PORT failed: port is already allocated.
Removal e best-effort (warn-only se falhar). Inspecione os logs antes de retentar:
docker logs <container_name> # logs do container que falhou (ainda disponiveis ate cleanup)
runner deploy <app> --verbose # retry com output completoLock recovery (v2.26.4+)
Cada deploy adquire <app_dir>/.deploy.lock. A stale-detection libera o lock automaticamente quando:
- O PID gravado nao existe mais (processo morreu sem release)
- O lock e mais velho que
LOCK_MAX_AGE_MINUTES(default 30min)
Se nenhuma dessas heuristicas dispara mas voce SABE que o deploy esta preso:
runner deploy <app> --force-unlock
# [deploy] --force-unlock: removed /data/apps/<app>/.deploy.lock
# (deploy continua normal apos a remocao)Quando NAO usar --force-unlock: se houver um runner deploy real rodando em outra sessao. Confirme com ps -ef | grep "runner deploy <app>" antes.
Protecao contra Retry Infinito (v1.4.1)
Quando o deploy automatico (fetch --deploy) falha, o Runner registra o commit que falhou no estado da app. Se o mesmo commit falhar novamente, o contador de retries incrementa. Ao atingir max_deploy_retries (padrao: 3), o Runner bloqueia o deploy automatico daquele commit.
Commit abc123 → deploy falhou (1/3)
Commit abc123 → deploy falhou (2/3)
Commit abc123 → deploy falhou (3/3)
Commit abc123 → bloqueado (aguardando novo push)
Commit def456 → novo commit, contador resetado → deploy executaPara configurar o limite:
# /opt/runner/config.yml
max_deploy_retries: 3 # padrao: 3, 0 = ilimitadoO deploy manual (runner deploy meu-app) nao e afetado pelo limite — sempre executa.
Health Check
O health check verifica:
- Container iniciou
- Endpoint
/healthretorna 200 - Container esta
healthy
O timeout e calculado automaticamente com base nos parametros de healthcheck do .deploy.yml:
timeout = start_period + (interval + timeout) * retries + bufferNotificacoes
Mensagens enviadas:
- Deploy Iniciado — ao comecar o pipeline
- Deploy Concluido — ao finalizar com sucesso
- Deploy Falhou — em caso de erro (inclui versao anterior ativa e erro extraido)
A mensagem de falha extrai a linha de erro real de outputs verbosos (Docker BuildKit, npm, compilador Rust) em vez de mostrar o output truncado.
Exemplo de notificacao de falha:
❌ Deploy Falhou
📦 Projeto: meu-app
🌐 Instance: production
🏷️ Versão: abc1234
🔄 Rollback: v1.0.0 (versão anterior mantida)
⚠️ Erro:
docker build failed: ERROR: process "/bin/sh -c npm run build" did not complete successfullyExit Codes
| Codigo | Significado |
|---|---|
| 0 | Sucesso |
| 1 | Erro generico |
| 2 | Config invalida |
| 3 | Health check falhou |
| 4 | Testes falharam |
| 5 | Rollback executado |
Logs
# Ver historico
runner logs history --app /data/apps/meu-app
# Ver log do ultimo deploy
runner logs tail --app /data/apps/meu-appEstrutura Apos Deploy
/data/apps/meu-app/
├── .deploy.yml
├── .env
├── .secrets
├── .runner/
│ └── secrets.enc # Secrets encriptados (se ckey configurada)
└── src/
└── production/
├── v1.0.0/
├── v1.0.1/
└── current -> v1.0.1Secrets Encriptados
Se a app foi registrada com --ckey, o Runner encripta .env e .secrets apos cada deploy e persiste como .runner/secrets.enc no repositorio. Isso permite recuperacao zero-touch em caso de perda do servidor.
Consulte o guia Secrets e Encriptacao para detalhes completos.