Docker HEALTHCHECK
debt(d3/e3/b5/t5)
Closest to 'default linter catches the common case' (d3). Hadolint (cited in detection_hints.tools) is a widely-used Dockerfile linter that flags missing HEALTHCHECK instructions. It's not a compiler error (d1), but it's more accessible than specialist SAST tools (d5) since hadolint is commonly integrated into CI pipelines for Dockerfile validation.
Closest to 'simple parameterised fix' (e3). The quick_fix shows a single line addition to the Dockerfile: HEALTHCHECK CMD curl -f http://localhost/health || exit 1. However, common_mistakes reveal you may also need to ensure curl is installed and create a /health endpoint if one doesn't exist, making it slightly more than a one-line patch but still a localised, parameterised fix within one component.
Closest to 'persistent productivity tax' (b5). Missing HEALTHCHECK affects all production deployments across web and cli contexts (per applies_to). Without it, orchestrators cannot automatically detect and recover from unhealthy containers, meaning every deployment relies on manual monitoring or external health checks. This creates ongoing operational overhead that affects multiple work streams but doesn't quite reach the level of shaping every change (b7).
Closest to 'notable trap' (t5). The misconception explicitly states the trap: developers assume 'if the container process is running, the container is healthy.' This is a documented gotcha that most devs eventually learn after encountering a deadlocked or error-serving container that stayed 'up'. It's not catastrophic (t9) since the failure mode is observable, but it contradicts the intuitive assumption about container health.
Also Known As
TL;DR
Explanation
HEALTHCHECK CMD defines a command run periodically inside the container. Docker tracks three states: starting (grace period), healthy, unhealthy. After a configurable number of consecutive failures (--retries), the container is marked unhealthy. Docker Swarm and Kubernetes use this signal to restart unhealthy containers and remove them from load balancer rotation. Without HEALTHCHECK, a container that is running but serving errors is invisible to the orchestrator.
Common Misconception
Why It Matters
Common Mistakes
- Setting --interval too short on slow-starting apps — container is marked unhealthy before it has finished initialising.
- Not having a dedicated /health endpoint — using the app's main route mixes health checks with request logs.
- Forgetting that curl must be installed in the container image for curl-based health checks.
Avoid When
- Do not use the main application route as the health check endpoint — it pollutes access logs and may have side effects.
- Do not set --start-period too short for slow-starting applications — they will be killed before they finish initialising.
When To Use
- Add HEALTHCHECK to every production Docker image — it is the orchestrator's only window into application health.
- Use a dedicated /health endpoint that checks all critical dependencies (DB, cache, queue).
Code Examples
# No HEALTHCHECK — orchestrator has no visibility into app health
FROM php:8.3-fpm
COPY . /var/www/html
# Container marked 'running' even if PHP-FPM is deadlocked
# Dockerfile
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
# PHP health endpoint
<?php
header('Content-Type: application/json');
// Check DB connection
try {
$pdo = getDatabaseConnection();
$pdo->query('SELECT 1');
echo json_encode(['status' => 'ok']);
} catch (\Throwable $e) {
http_response_code(503);
echo json_encode(['status' => 'error', 'detail' => 'db unavailable']);
}