Healthchecks & Boot Polling
Relevant source files
The following files were used as context for generating this wiki page:
Healthchecks and Boot Polling in Kamal ensure that application containers are fully functional and ready to receive traffic before the deployment process proceeds or old containers are removed. This mechanism provides a safety net during zero-downtime deploys by verifying container status through various methods including Docker healthchecks, HTTP probes, and custom execution commands.
The system is integrated into the core deployment workflow, specifically during the kamal app boot phase. It prevents "drift" where a configuration expects a healthcheck that the container does not report, and it manages the transition period defined by readiness_delay for roles that lack explicit healthchecks.
Sources: lib/kamal/cli/main.rb:29-57, test/cli/healthcheck/poller_test.rb:26-34
Healthcheck Configuration
Kamal supports multiple types of healthchecks configured per role. These configurations determine how Kamal validates a container's readiness.
Configuration Types
| Type | Configuration Key | Description |
|---|---|---|
| HTTP Probe | port, path | Uses curl inside the container to check a specific URL. Defaults to /up if only port is provided. |
| Custom Command | cmd | Runs a custom shell command within the container to determine health. |
| Exec Probe | exec | Runs a command from the deploy host against the container using docker exec. Does not emit Docker healthcheck flags. |
| Docker Options | options: health-cmd | A hand-rolled Docker healthcheck defined in the container options. |
| None / Opt-out | healthcheck: false | Explicitly accepts the container as ready after the readiness_delay expires. |
Sources: lib/kamal/configuration/role/healthcheck.rb:7-13, test/configuration/role/healthcheck_test.rb:5-15, lib/kamal/configuration.rb:397-407
Healthcheck Arguments
When using port, path, or cmd, Kamal translates these into Docker --health-* flags during the docker run command.
Boot Polling & Readiness Gating
The polling mechanism waits for a container to reach a "healthy" state before proceeding with the deployment.
Polling Logic
- Healthy Status: If the container reports
healthy, the poller returns successfully. - Drift Detection: If a role defines a healthcheck but the container reports
no-healthcheck, aDriftErroris raised. This prevents false positives where a container is running but its healthcheck is missing. - Timeouts: The poller respects the
deploy_timeout(default 30s). If the timeout is reached before the container is healthy, the deploy fails. - Readiness Delay: For roles without healthchecks, Kamal sleeps for the duration of the
readiness_delay(default 7s) before assuming the container is ready.
Sources: test/cli/healthcheck/poller_test.rb:7-24, test/cli/healthcheck/poller_test.rb:45-56, lib/kamal/configuration.rb:271-282
Readiness Lifecycle
The following sequence diagram illustrates the polling flow during a deployment:
Diagnostic Readiness (Doctor)
The kamal doctor command performs pre-deployment readiness checks to identify potential issues with healthchecks and infrastructure.
Doctor Checks
- Ports: Verifies that ports 80 and 443 are free or held by an existing
kamal-proxy. - DNS/Certificates: Checks if the service domain resolves to the target hosts and if certificates are valid.
- Readiness Source: Identifies the readiness source for every role (e.g.,
kamal-proxy health check,docker healthcheck, orNONE). - Docker Socket: Inspects if
/var/run/docker.sockis mounted, which is required forproxy/sleepfunctionality.
Sources: lib/kamal/cli/doctor.rb:10-23, test/cli/doctor_test.rb:14-36, test/cli/doctor_test.rb:148-160
Readiness Summary Table
The CLI provides a banner during deployment summarizing the readiness state of each role.
| Role | Readiness Description | Source |
|---|---|---|
| Web | kamal-proxy health check /path | Proxy |
| Worker | NONE (old container stops 7s after boot) | Default Delay |
| Listener | healthcheck /readyz:7434 | Healthcheck Block |
| Prober | healthcheck exec probe (bin/check) | Exec Probe |
Sources: lib/kamal/cli/main.rb:533-540, test/cli/main_test.rb:569-577
Implementation Details
Healthcheck Configuration Schema
The Kamal::Configuration::Role::Healthcheck class handles the validation and argument generation for healthchecks.
# lib/kamal/configuration/role/healthcheck.rb
def cmd
config["cmd"] || "curl -f http://localhost:#{config["port"]}#{config["path"] || "/up"} || exit 1"
end
def args
return [] if exec?
[].tap do |args|
args << "--health-cmd" << argumentize(cmd)
args << "--health-interval" << argumentize(interval_with_unit) if interval
args << "--health-timeout" << argumentize(timeout_with_unit) if timeout
args << "--health-retries" << argumentize(retries) if retries
args << "--health-start-period" << argumentize(start_period_with_unit) if start_period
args << "--health-start-interval" << argumentize(start_interval_with_unit) if start_interval
end
end
Sources: lib/kamal/configuration/role/healthcheck.rb:20-40
Important Constraints
- Shell Expansion: Healthcheck commands and Docker health-options cannot contain
${...}braced expansions, as these would expand on the deploy host rather than inside the container. - Conflict Prevention: A
healthcheckblock cannot coexist with a hand-rolledoptions/health-cmd. - Exec Probes: Because
execprobes are polled from the deploy host, they cannot be combined with Docker-specific keys likeinterval,timeout, orretries.
Sources: lib/kamal/configuration/role/healthcheck.rb:73-95, test/configuration/role/healthcheck_test.rb:88-106
Summary
Healthchecks and Boot Polling form a critical layer of Kamal's deployment stability. By providing granular control over how roles are validated—ranging from simple port checks to host-side execution probes—Kamal ensures that traffic is only routed to containers that are genuinely ready to handle requests. The diagnostic tools in the doctor command further complement this by verifying environment readiness before a deploy is even attempted.