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.yml com campo healthcheck: configurado
  • Para mode: http e mode: 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: /health

Sintaxe completa:

healthcheck:
  mode: http
  path: /health
  port: 8000
  timeout: 30s
  interval: 10s
  retries: 3
  start_period: 0s

O 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: 3306

Sintaxe completa:

healthcheck:
  mode: tcp
  tcp: 3306
  timeout: 30s
  interval: 10s
  retries: 3
  start_period: 60s

O 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: 30s

O 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: exit

Nã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 --rm sob demanda
  • O cron não faz deploy automático — mode: exit sinaliza 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.

By Borlot.com.br on 27/05/2026