O Docker Healthcheck no Node.js permite que o runtime marque um container como saudável, não saudável ou ainda em inicialização. O processo pode estar ativo e a porta aberta, mas a aplicação pode ter falhado ao carregar configuração, conectar ao banco ou processar o event loop. O healthcheck adiciona uma verificação periódica além do simples estado “running”.
Essa informação pode ser usada por Docker Compose, ferramentas de monitoramento e plataformas que observam o estado do container. Ela não reinicia automaticamente um container no Docker Engine isolado apenas porque ficou unhealthy; a ação depende do orquestrador ou da política externa.
Neste guia, você aprenderá a criar um endpoint, configurar HEALTHCHECK, escolher intervalos e timeouts, evitar dependências excessivas, trabalhar com Compose, usar scripts em Node.js, integrar com shutdown e testar falhas.
O que é HEALTHCHECK?
HEALTHCHECK é uma instrução do Dockerfile que executa um comando dentro do container. A documentação oficial de HEALTHCHECK descreve opções, códigos de saída e estados. A documentação do Docker Compose sobre ordem de startup explica dependências condicionadas à saúde.
Para construir imagens menores e seguras, consulte Docker Multi-stage para Node.js. Para endpoints de saúde, veja Health Checks no Node.js.
Estados do container
- starting: período inicial antes de sucessos suficientes;
- healthy: último teste teve sucesso;
- unhealthy: falhas consecutivas atingiram o limite.
O estado do processo continua separado. Um container unhealthy pode permanecer executando.
Endpoint básico
app.get('/health/live', (req, res) => {
res.status(200).json({ status: 'ok' });
});O handler deve ser rápido e não exigir autenticação externa.
HEALTHCHECK com wget
HEALTHCHECK \
--interval=30s \
--timeout=3s \
--start-period=20s \
--retries=3 \
CMD wget --no-verbose --tries=1 \
--spider http://127.0.0.1:3000/health/live \
|| exit 1A imagem precisa conter wget. Instalar uma ferramenta apenas para o healthcheck aumenta tamanho e superfície de ataque.
Healthcheck em Node.js
Uma alternativa é usar o próprio runtime:
// scripts/healthcheck.cjs
const http = require('node:http');
const request = http.get({
hostname: '127.0.0.1',
port: process.env.PORT || 3000,
path: '/health/live',
timeout: 2000
}, response => {
response.resume();
process.exit(response.statusCode === 200 ? 0 : 1);
});
request.on('timeout', () => {
request.destroy();
});
request.on('error', () => {
process.exit(1);
});No Dockerfile:
HEALTHCHECK --interval=30s --timeout=3s \
--start-period=20s --retries=3 \
CMD ["node", "scripts/healthcheck.cjs"]Códigos de saída
0: saudável;1: não saudável;2: reservado; evite usar.
Interval
--interval define a frequência. Um teste a cada segundo gera carga e ruído; um teste a cada cinco minutos demora para detectar falha. Valores entre 10 e 30 segundos são comuns, mas devem ser medidos.
Timeout
--timeout limita cada execução. O script também deve definir timeout próprio, porque uma conexão pendurada pode não encerrar de forma limpa.
Retries
--retries exige falhas consecutivas antes de marcar unhealthy. Isso evita que uma pausa curta de garbage collection ou pico de CPU altere o estado.
Start period
--start-period oferece uma janela de inicialização. Falhas nesse período não contam normalmente para o limite, permitindo carregar configuração, módulos e conexões.
Start interval
Versões modernas do Dockerfile podem oferecer --start-interval para frequência diferente durante o período inicial. Verifique suporte no Docker usado pelo ambiente.
Liveness versus readiness
Docker HEALTHCHECK possui um único estado. Ele não distingue claramente “o processo deve reiniciar” de “não envie tráfego”. Em Kubernetes, use probes separadas.
Consulte Probes Kubernetes em Node.js.
Banco no healthcheck?
Depende da intenção. Se o healthcheck é usado para reiniciar o container, falhar porque o PostgreSQL está indisponível pode causar loops de reinício sem corrigir a dependência. Prefira um endpoint mínimo para liveness e outro de readiness para dependências.
Endpoint de readiness
app.get('/health/ready', (req, res) => {
const ready = state.started
&& state.databaseConnected
&& !state.shuttingDown;
res.status(ready ? 200 : 503).json({
status: ready ? 'ready' : 'not_ready'
});
});Docker Compose
services:
api:
build: .
healthcheck:
test: ["CMD", "node", "scripts/healthcheck.cjs"]
interval: 10s
timeout: 3s
retries: 5
start_period: 20sA configuração do Compose pode substituir a instrução do Dockerfile.
Dependência saudável no Compose
services:
api:
depends_on:
db:
condition: service_healthyIsso controla ordem inicial, mas a aplicação ainda precisa lidar com o banco caindo depois.
Healthcheck do PostgreSQL
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
timeout: 3s
retries: 10Não coloque senha no comando visível. Use configuração segura.
Imagens distroless
Imagens distroless podem não ter shell, curl ou wget. Use a forma JSON do CMD e inclua um script JavaScript no bundle, ou delegue a verificação ao orquestrador.
Shell form versus exec form
HEALTHCHECK CMD curl -f http://localhost:3000/health || exit 1A forma shell depende de /bin/sh. A forma exec evita shell:
HEALTHCHECK CMD ["node", "scripts/healthcheck.cjs"]Não use localhost externo
O comando roda dentro do container. Use 127.0.0.1 e a porta interna, não o endereço publicado no host.
IPv6
Se a aplicação escuta apenas IPv6 ou apenas IPv4, o healthcheck precisa usar a família correta. Teste o binding real do servidor.
Autenticação
Não exija OAuth ou banco para o endpoint mínimo. Restrinja a exposição pela rede e retorne apenas um status pequeno, sem informações internas.
Dados sensíveis
Evite resposta com:
- URL do banco;
- versão de bibliotecas;
- nomes de hosts internos;
- tokens;
- stack traces;
- lista completa de dependências.
Event loop bloqueado
Um endpoint HTTP não responde se o event loop está bloqueado. Isso detecta travamentos, mas thresholds precisam tolerar pausas transitórias.
Veja Event Loop no Node.js.
Graceful shutdown
Ao receber SIGTERM, marque readiness como falsa e feche o servidor. O HEALTHCHECK pode falhar durante a parada, mas o processo deve concluir no prazo.
Consulte Graceful Shutdown no Node.js.
Reinício automático
No Docker Engine isolado, unhealthy não equivale a restart. Use Compose com ferramenta externa, Swarm, Kubernetes ou monitoramento que tome a ação adequada.
Não mate o processo no endpoint
O healthcheck deve informar estado. Não chame process.exit() dentro do handler por uma falha temporária do banco.
Inspecionando saúde
docker inspect \
--format='{{json .State.Health}}' \
my-containerO histórico contém códigos e saída dos últimos testes.
Limite de saída
A saída do comando pode aparecer no inspect. Não imprima segredos ou respostas completas.
Logs
Evite registrar cada chamada do healthcheck no log normal. Filtre a rota ou reduza o nível para impedir ruído.
Observabilidade
Monitore:
- mudanças para unhealthy;
- duração do check;
- falhas consecutivas;
- reinícios;
- tempo de startup;
- event loop delay;
- uso de CPU e memória.
Testando localmente
docker build -t my-api .
docker run --name my-api -p 3000:3000 my-api
docker inspect my-apiEspere vários intervalos e confirme a transição para healthy.
Simulando falha
Adicione uma flag apenas em ambiente de teste para fazer o endpoint retornar 500. Verifique que o estado muda após o número esperado de tentativas.
Testando startup lento
Atrase a inicialização e valide que start-period evita marcação prematura como unhealthy.
Erros comuns
- Ferramenta ausente: curl ou wget não existe na imagem.
- Timeout sem abortar socket: o script fica pendurado.
- Banco na liveness: falha externa causa restart loop.
- Endpoint pesado: o próprio check gera carga.
- Intervalo curto: logs e CPU aumentam.
- Esperar restart automático: Docker apenas marca unhealthy.
- Expor detalhes: o endpoint vaza arquitetura.
Boas práticas
- Use endpoint mínimo.
- Defina timeout no Docker e no script.
- Configure start-period.
- Tolere falhas transitórias.
- Não instale shell sem necessidade.
- Separe liveness e readiness quando o orquestrador permitir.
- Não registre cada sucesso.
- Teste imagem final.
- Trate SIGTERM.
- Monitore mudanças de estado.
Conclusão
O Docker Healthcheck no Node.js adiciona uma verificação funcional ao estado do container. Um script leve pode confirmar que o servidor responde, enquanto intervalos, timeout, start-period e retries evitam falsos positivos.
O healthcheck deve permanecer simples e seguro. Dependências externas pertencem à readiness, e o mecanismo de restart precisa ser definido pelo orquestrador. Com testes de startup, travamento e shutdown, a imagem informa seu estado sem criar carga ou loops de reinício.



