runner cleanup

Limpeza de recursos nao utilizados: versoes antigas, containers orfaos, PRs expirados, imagens Docker e build cache.

Sintaxe

runner cleanup [OPTIONS]

Opcoes

Opcao Descricao
--project <NAME> Limpar apenas versoes de um projeto especifico. Fase default do project: roda quando nenhuma flag de fase global e passada. Combinado com fases globais (--images, --orphans, etc.) e ignorado com WARN — elas nao operam por projeto (v2.50.2, #49)
--expired Limpar instancias efemeras expiradas
--orphans Limpar containers orfaos (versoes antigas rodando)
--prs Limpar PRs expirados (TTL) ou merged/closed (via GitHub API)
--images Remover imagens Docker nao utilizadas de projetos gerenciados. v2.53.3+: tambem aplica o teto do build cache (auto_prune_build_cache_max) — na pratica o cache costuma ser maior que as imagens. Use --build-cache explicito para controlar.
--build-cache [FILTER] Prune do Docker buildkit cache por idade. Sem valor (v2.53.4+): usa docker.auto_prune_build_cache do config.yml (fallback 72h) — antes era 72h hardcoded, ignorando o config. Use all para podar tudo, inclusive cache recente.
--dry-run Preview sem executar (mostra o que seria removido)
-V, --verbose Output detalhado
-x, --exact Desliga a resolucao por query no --project: um alvo so
-y, --yes Confirma quando --project casa varios alvos do mesmo projeto. Nao autoriza atravessar projetos

Exemplos

Containers orfaos

runner cleanup --orphans --dry-run
runner cleanup --orphans

PRs expirados

runner cleanup --prs --dry-run
runner cleanup --prs

Imagens Docker

runner cleanup --images --dry-run
runner cleanup --images

Remove imagens no formato {project}:{version} que nao estao em uso por nenhum container rodando. Apos remover, executa docker image prune -f para limpar dangling layers.

Build cache

Atencao: o filtro de idade so evicta cache mais velho que o valor. Num servidor que deploya varias vezes por dia, o cache recente nunca e alcancado — se voce quer recuperar espaco AGORA, use --build-cache all. Para limitar o crescimento de forma continua, configure o teto de tamanho (docker.auto_prune_build_cache_max), que e aplicado automaticamente pos-build.

runner cleanup --build-cache              # Prune cache > 72h (default)
runner cleanup --build-cache 24h          # Prune cache > 24h
runner cleanup --build-cache 168h         # Prune cache > 7 dias
runner cleanup --build-cache all          # Prune TUDO (proximo build refaz do zero)
runner cleanup --build-cache --dry-run    # Preview (mostra docker builder du)

Combo completo

runner cleanup --images --build-cache 72h --orphans --prs

Limpeza automatica

O pipeline de deploy limpa automaticamente:

  • Versoes antigas: Ao deployar, versoes que excedem keep_versions sao removidas (container + source dir + imagem Docker)
  • PRs expirados: No fetch --deploy, PRs com TTL expirado sao removidos automaticamente (configuravel via auto_cleanup_prs no config.yml)

`--reset-root` (v2.15.0+) — migracao do fluxo de clone

Ferramenta de migracao opt-in pra apps registradas antes da v2.15.0, onde runner add clonava o repo inteiro na raiz do app dir (resultando em codigo duplicado entre raiz e src/{instance}/{ver}/).

Comportamento

Remove tudo do app dir exceto a whitelist:

  • dirs preservados: src/, data/, logs/, pull/, .runner/
  • files preservados: .deploy.yml, .env, .secrets

Cria snapshot automatico (trigger pre-reset-root) antes de remover qualquer coisa. Pra reverter:

runner config-backups list --app meu-app   # acha o snapshot
runner config-backups restore <id>          # restaura

Uso

# Preview (nao remove nada)
runner cleanup --reset-root --project meu-app --dry-run

# Executa em uma app especifica
runner cleanup --reset-root --project meu-app

# Executa em TODAS as apps registradas
runner cleanup --reset-root

Por que rodar

Apps registradas pre-2.15.0 tem essa estrutura tipica:

/data/apps/minha-api/
├── app/                   ← codigo da raiz (clone original)
├── bootstrap/
├── composer.json
├── ...
└── src/production/v1/
    ├── app/               ← MESMO codigo, duplicado!
    └── ...

Apos --reset-root:

/data/apps/minha-api/
├── .deploy.yml
├── .env, .secrets
├── .runner/secrets.enc
├── data/, logs/, pull/
└── src/production/v1/    ← codigo so aqui

Quando NAO usar

  • Apps recem-registradas (v2.15.0+) ja nascem limpas, nao precisa
  • Apps com bind-mount customizado pra raiz (verifique docker inspect antes)

Cron recomendado

# Semanal: imagens + build cache + containers orfaos
0 5 * * 0 /opt/runner/runner cleanup --images --build-cache 72h --orphans

# Diario: PRs expirados/merged
0 2 * * * /opt/runner/runner cleanup --prs

Multiplos alvos e a fronteira do projeto (v2.80.0+)

--project <NAME> nao e um nome exato: e uma query, casada por segmento. runner cleanup --project ccs alcanca ccs/sys, ccs/front e ccs/worker — replicar o comando nos sistemas de um projeto e o desenho do runner, nao um acidente.

Situacao Comportamento
1 alvo Executa direto, sem cerimonia
N alvos, mesmo projeto Lista os alvos e pede confirmacao. -y, --yes dispensa
N alvos, projetos distintos Terminal: pergunta. Cron/CI (sem TTY): aborta com exit != 0. Nenhuma flag autoriza

O gate so entra quando uma fase project-scoped vai rodar de fato. Fases globais explicitas (--images, --orphans, --expired, --prs, --build-cache) ignoram o --project e nao sao gateadas — gatear nelas abortava cron sem proteger nada (#49).

O "projeto" aqui e a raiz antes do primeiro hifen: ccs-front e ccs-sys sao o mesmo projeto (ccs); ccs-front e nfse-front nao sao.

Por que `--yes` nao autoriza atravessar

--yes e passado por habito, em script e cron. Se valesse para o cruzamento, o gate morreria exatamente onde ninguem esta olhando. Uma query casa por segmento e deveria cair dentro de uma familia — atravessar e anomalia, nao intencao.

ERROR cleanup --project atravessa 2 projetos (ccs, nfse) em 4 alvos:
  - ccs/sys
  - ccs/front
  - nfse/sys
  - nfse/front

Uma query casa por segmento e deveria cair dentro de UMA família — atravessar aqui é anomalia, não intenção, e por isso nenhuma flag autoriza.
Este comando não opera em massa entre projetos: rode um projeto por vez.
Para um alvo só: -x

Em terminal interativo o cruzamento pergunta em vez de abortar. Em cron/CI (sem TTY) aborta com exit != 0.

Saidas:

  • -x, --exact — desliga a query e mira um alvo so
  • rodar um projeto por vez
By Borlot.com.br on 17/04/2026