Modos de healthcheck
O Runner suporta cinco modos de probe para verificar se um deploy foi bem-sucedido. Esta página detalha cada modo: sintaxe mínima, sintaxe completa, quando usar e armadilhas comuns.
Pré-requisitos
- Runner v2.30.10+
.deploy.ymlcom campohealthcheck:configurado- Para
mode: httpemode: tcp: porta da app acessível dentro do container
Resumo dos modos
| Modo | Como funciona | Use quando |
|---|---|---|
http (default) |
HTTP GET em path, espera 2xx |
App web com endpoint de saúde |
tcp |
TCP connect na porta | DB, Redis, app sem HTTP |
cmd |
Executa comando dentro do container | Probe customizada, imagem distroless |
exit |
Roda container, espera exit 0 | CLI tool, scanner, job one-shot |
skip |
Sem probe — aceita running |
Apenas para debug local; nunca em produção |
Modo http
O Runner injeta um healthcheck que faz GET HTTP no path configurado. Espera status 2xx.
Sintaxe mínima:
healthcheck:
path: /healthSintaxe completa:
healthcheck:
mode: http
path: /health
port: 8000
timeout: 30s
interval: 10s
retries: 3
start_period: 0sO campo mode: http é opcional — quando path: está presente e mode: está ausente, o Runner assume http.
Como o Runner injeta o healthcheck
Em modo IMAGE (imagem do registry), o runner tenta curl, com fallback para wget (busybox):
(curl -sf http://127.0.0.1:PORT/health || wget -q -O /dev/null http://127.0.0.1:PORT/health)Em modo BUILD (Dockerfile do repo), usa /dev/tcp do bash:
bash -c 'echo -e "GET /health HTTP/1.0\r\n..." > /dev/tcp/127.0.0.1/PORT'Se o Dockerfile declara HEALTHCHECK, o Runner respeita e não injeta nada. Ver Sistema de Health Check para detalhes sobre herança.
Quando usar
- Apps Flask, Express, FastAPI, Rails — qualquer app que exponha
/health - Frontends servidos por Caddy ou nginx
- Qualquer container que fique rodando e responda HTTP
Pitfalls comuns
Imagem Alpine sem curl: Alpine tem wget (busybox) mas não curl. O Runner tenta os dois — geralmente funciona. Se não funcionar, declare HEALTHCHECK no Dockerfile.
Imagem Alpine em modo BUILD: o bash não existe em Alpine puro, então /dev/tcp falha. Declare HEALTHCHECK no Dockerfile com wget.
Path sem /: o path deve começar com /. runner validate retorna erro se omitido.
Endpoint que sempre retorna 200: healthchecks que retornam 200 sem verificar dependências reais (banco, fila) não detectam falhas de aplicação. Configure o endpoint para checar conexões críticas.
Modo tcp
O Runner faz TCP connect na porta. Considera saudável se a conexão for aceita.
Sintaxe mínima:
healthcheck:
tcp: 3306Sintaxe completa:
healthcheck:
mode: tcp
tcp: 3306
timeout: 30s
interval: 10s
retries: 3
start_period: 60sO Runner injeta nc -z 127.0.0.1 <porta> com fallback para /dev/tcp.
Quando usar
- Bancos de dados (MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017)
- Redis (6379), RabbitMQ (5672), SMTP (25)
- Qualquer serviço que aceita TCP mas não fala HTTP
- Apps PHP-FPM (FastCGI na porta 9000)
Pitfalls comuns
Porta diferente do port: do manifesto: o campo tcp: e o campo port: são independentes. port: é a porta que o Traefik usa para roteamento HTTP. tcp: é a porta que o healthcheck verifica. Em apps não-HTTP, os dois podem ser diferentes (ou port: 0 com tcp: definido).
Start period insuficiente para bancos: MySQL e PostgreSQL podem demorar 30-60s para aceitar conexões após iniciar. Use start_period: 60s ou mais.
Modo cmd
O Runner passa um comando custom diretamente ao container (exec form). O container executa o comando e o Runner verifica o exit code — 0 é saudável.
Sintaxe mínima:
healthcheck:
cmd: ["/app/healthcheck"]Sintaxe completa:
healthcheck:
mode: cmd
cmd: ["/app/bin/healthcheck", "--strict", "--timeout", "5"]
timeout: 30s
interval: 10s
retries: 3
start_period: 30sO cmd: recebe uma lista de strings (exec form). Não use string única — o Runner não passa pelo shell.
Quando usar
- Imagens distroless (sem shell, sem curl, sem wget)
- Binários Go ou Rust com healthcheck embutido
- Probes que verificam mais que HTTP — conexão ao banco, fila disponível, licença válida
- Imagem já tem um binário de healthcheck (
/usr/local/bin/healthcheck)
Pitfalls comuns
String em vez de lista: cmd: "/app/healthcheck" (string) não é aceito. Use cmd: ["/app/healthcheck"] (lista).
Lista vazia: cmd: [] retorna erro de validação. A lista deve ter pelo menos um elemento.
Binário não existe na imagem: se o comando não for encontrado, o Docker marca unhealthy imediatamente. Valide com docker exec <container> /app/healthcheck antes de configurar.
Exit code não-zero em condição saudável: alguns scripts retornam 1 em warnings. O Runner trata qualquer exit code diferente de 0 como falha.
Modo exit
O Runner não mantém container permanente. Em vez disso, roda o container, aguarda ele terminar e verifica o exit code — 0 indica sucesso.
Sintaxe (única forma):
healthcheck:
mode: exitNão há campos adicionais como path, interval ou retries — o modo exit tem comportamento próprio.
Comportamento especial
| Trigger | Ação |
|---|---|
runner fetch --deploy (cron automático) |
Skipa o deploy — só atualiza artefatos |
runner deploy (manual) |
Builda/puxa imagem, valida com docker run --rm <image> --version (exit 0 = OK) |
Características:
- Sem container permanente rodando
- Sem rota Traefik configurada
- Imagem fica disponível para
docker run --rmsob demanda - O cron não faz deploy automático —
mode: exitsinaliza que a app não é um serviço
Quando usar
- Scanners e ferramentas CLI (ex: CCS Scanner)
- Batch jobs que rodam sob demanda
- Apps que o operador invoca manualmente com
docker run --rm - Utilitários que devem ser atualizados mas não ficam rodando
Pitfalls comuns
Esperar que o cron faça deploy: com mode: exit, o cron só busca novos artefatos — não faz docker run. Use runner deploy manual para atualizar a imagem no servidor.
Usar mode: exit para app que fica rodando: se a app precisa responder requests, mode: exit impede que o Runner confirme que o container subiu corretamente.
Modo skip
O Runner aceita qualquer container no estado running como saudável. Nenhuma probe é executada.
Sintaxe:
healthcheck:
path: ""Ou sem campo healthcheck: no manifesto — o comportamento é o mesmo.
Quando usar
Nunca em produção. O modo skip existe exclusivamente para debug local.
Em produção, um container pode subir, reportar running ao Docker e imediatamente travar a aplicação internamente. Sem probe, o Runner não detecta isso e o deploy é marcado como sucesso.
Pitfalls comuns
Worker sem porta tratado como skip acidental: workers sem porta HTTP frequentemente ficam com path: "" ou sem healthcheck. Isso é aceitável se o worker é monitorado por outro mecanismo (heartbeat no Redis, por exemplo). Se não houver monitoramento, o Runner não detecta crash — apenas o próximo fetch --deploy vê que o container morreu.
Remover healthcheck como "fix" para timeout: se o healthcheck está dando timeout, a causa raiz é a app estar lenta ou com bug — não o healthcheck. Remover a probe esconde o problema.
Campos comuns de timing
Os campos timeout, interval, retries e start_period funcionam da mesma forma nos modos http, tcp e cmd:
| Campo | Default | Descrição |
|---|---|---|
start_period |
0s |
Grace period antes de começar as probes |
interval |
10s |
Intervalo entre probes |
timeout |
5s |
Timeout de cada probe individual |
retries |
3 |
Quantas falhas consecutivas antes de marcar unhealthy |
O Runner calcula o timeout total do deploy como:
timeout_total = start_period + (interval + timeout) × retries + 30s (buffer)Com os defaults: 0 + (10 + 5) × 3 + 30 = 75s.
Links relacionados
- Sistema de Health Check — fluxo completo, herança de Dockerfile, tolerância a unhealthy transitório
- Schema do .deploy.yml — referência completa do manifesto
- Healthcheck failed — recuperar após falha de probe (em breve)