README
¶
docker-health-go (htcheck)
A small, special-purpose HTTP client for lightweight health checks — designed
for use as a Docker HEALTHCHECK command in scratch or distroless images
that have no curl, wget, or shell.
Why this exists
Docker (and Compose) lets you declare a HEALTHCHECK so the engine knows
whether the container is healthy. The check is just a command, and the usual
choice is curl or wget. That's fine for a fat base image — but if you
build on FROM scratch or gcr.io/distroless/static, neither tool is
available, and pulling libcurl plus its transitive deps (OpenLDAP, NSS, …)
just to do a single HTTP GET is wasteful.
htcheck is a single static binary (~5–6 MB stripped) that does exactly one
thing: GET a URL, optionally verify a JSON field, and exit with the right
code for Docker.
When not to use this
- Kubernetes — use
httpGetin liveness/readiness probes. The kubelet performs the request itself; no binary in the container is needed. - Images that already ship a shell + wget (Alpine, BusyBox-based) —
wget --spider -q URLcovers the basic case in one line. - Your own Go service — consider adding a
myapp healthchecksubcommand so you don't ship a second binary at all.
The sweet spot for htcheck is genuinely minimal images (scratch,
distroless) where Docker (not Kubernetes) supervises the container.
Build
Requires Go 1.21+. A Makefile wraps the common workflows:
make help # list all targets
make build # build for the host platform
make build-linux # cross-compile static linux/amd64 + linux/arm64 into dist/
make test # run tests
make check # vet + lint + vulncheck + test
Quality targets:
| Target | What it runs |
|---|---|
vet |
go vet ./... |
lint |
staticcheck ./... |
vulncheck |
govulncheck ./... |
check |
all of the above plus go test |
lint and vulncheck require their tools on $PATH — install once with:
make tools # installs staticcheck and govulncheck via 'go install'
Cross-built binaries land in dist/ as htcheck-linux-amd64 and
htcheck-linux-arm64, statically linked and stripped, ready to COPY into
a scratch image.
Usage
htcheck [flags]
-u, --url string health endpoint to check (default "http://localhost/")
-p, --path string optional JSON path (gjson syntax) to check
-v, --value string expected JSON value
-t, --timeout duration request timeout (default 5s)
-k, --insecure skip TLS certificate verification
-q, --quiet suppress log output
-h, --help show help
Exit codes follow Docker's healthcheck contract:
0 healthy, 1 unhealthy. (2 is reserved by Docker and never returned.)
In a Dockerfile
Plain endpoint check:
COPY ./htcheck /usr/bin/
HEALTHCHECK --interval=5m --timeout=3s \
CMD ["/usr/bin/htcheck", "-u", "http://localhost/"]
Spring Boot Actuator (/actuator/health returns {"status":"UP"}):
COPY ./htcheck /usr/bin/
HEALTHCHECK --interval=5m --timeout=3s \
CMD ["/usr/bin/htcheck", "-u", "http://localhost/actuator/health", "-p", "status", "-v", "UP"]
Self-signed internal TLS endpoint:
HEALTHCHECK CMD ["/usr/bin/htcheck", "-k", "-u", "https://localhost:8443/health"]
JSON path syntax
Paths use gjson syntax — dot-separated
keys, no leading $. A leading . is accepted for backwards compatibility
with older releases that used savaki/jq:
| Path | Matches |
|---|---|
status |
top-level field status |
.status |
same (legacy form) |
components.db.status |
nested field |
checks.0.status |
first array element's status |
Status code policy
Any 2xx response is healthy. The previous version accepted only 200,
which excluded common cases like 204 No Content.
Dependencies
Runtime:
spf13/pflag— POSIX-style flags (BSD-3-Clause)tidwall/gjson— JSON path queries (MIT)
Tests use only the Go standard library (net/http/httptest).
License
Copyright (c) Peter Klotz. Apache 2.0 — see LICENSE.
Documentation
¶
There is no documentation for this package.