Repository navigation
fix(docker): make Compose health checks reflect service state - #127
Merged
Merged
Conversation
- mysqld exporters ran `-h` as their health check, which is not a command, so they were always unhealthy. Probe the exporter's own /metrics endpoint over bash /dev/tcp (the image ships no curl/wget) and require `mysql_up 1`. - auth-db and dashboard-db ran psql over TCP, which needs a password. dashboard-db has no PGPASSWORD, so it never became healthy. Use pg_isready, which checks readiness without authenticating. - The gateway check piped into `exit`, which always returns 0, so the gateway reported healthy even when /health was unreachable. Use `curl -f` and `grep -q` so the pipeline status is the check result.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Three Docker Compose health checks don't report the real state of their service. Two of them are always unhealthy and one is always healthy. This PR changes only the
test:lines. The<<: *healthcheck-paramsanchors and all other service settings are unchanged.dbrepo-metadata-db-metrics,dbrepo-data-db-metricstest: -h/bin/sh -c "-h", which fails withIllegal option -h. Always unhealthy./metricsover bash/dev/tcpand requiremysql_up 1dbrepo-auth-db,dbrepo-dashboard-dbpsql -U … -h 127.0.0.1 … -c 'select version();'dashboard-dbhas noPGPASSWORD, so it getsfe_sendauth: no password. Always unhealthy.pg_isready -U … -h 127.0.0.1 -p 5432 -d …dbrepo-gateway-servicecurl -sSL 127.0.0.1:8080/health | grep 'UP' | exitexit, which returns 0. Always healthy, even when/healthcan't be reached.curl -fsS 127.0.0.1:8080/health | grep -q 'UP'Files changed (same edits in each, where the service/check exists):
.docker/docker-compose.yml: all three fixesdocker-compose.yml: Postgres and gateway (this file has no exporter services).live/config/includes.chroot_after_packages/etc/skel/docker-compose.yml: exporters and Postgres (the gateway in this file has no health check)Why these commands
bitnamilegacy/mysqld-exporter:0.15.1hasbashbut nocurlorwget, which I checked withcommand -v.mysqld_exporter --versionwould only prove the binary exists. The/dev/tcprequest checks that the exporter is serving on:9104and can reach its database (mysql_up 1). That's the state Prometheus depends on.pg_isreadyis inbitnamilegacy/postgresql:17.0.0at/opt/bitnami/postgresql/bin/pg_isready. It checks whether the server accepts connections without logging in, so it doesn't need a password and doesn't log auth failures every interval. On currentmain,auth-dbpasses because it setsPGPASSWORD. I changed it too so both Postgres services use the same password-independent check.nginx:1.28includescurl. With-f, an HTTP error makes curl fail. Withgrep -qat the end of the pipeline, the exit status becomes the check result.Type of Change
Related Issue
None filed. Found while deploying DBRepo with Docker Compose at ITB (see Additional Notes).
Checklist
Additional Notes
Field evidence (ITB deployment, DBRepo 1.13.4, Docker Compose)
In a production-style Compose deployment at ITB, both exporters were unhealthy because of the invalid
-hcommand, and both Postgres services stayed unhealthy because of the password-lesspsqlcheck. They became healthy after the checks were replaced on the server. That deployment usedmysqld_exporter --versionfor the exporters. This PR uses a stronger probe instead (see above).Reproduction on
main(3862655)I ran the affected services in an isolated Compose project (
-p hcrepro). An override file resetcontainer_name, removed hostports, and set healthcheckinterval: 5s/retries: 3so results came in quickly. Thetest:commands were the ones from.docker/docker-compose.yml. The gateway used a minimal nginx conf containing only thelocation = /healthblock fromdbrepo-gateway-service/dbrepo.conf, because the full conf won't start without its upstream hosts.Before (
docker inspect --format '{{json .State.Health}}', summarized):After (same project, recreated from this branch):
Failure cases are now detected
Gateway check against a dead port, run inside the gateway container:
Exporter with its database stopped (
docker stopondata-db):pg_isreadyagainst a closed port returnsno attemptwith exit 3.Not tested
docker-compose.ymlor the.livecopy. They have the sametest:strings as.docker/docker-compose.yml, which was the file I tested.dbrepo.conf, as described above..liveISO.condition: service_healthy, so startup order is unchanged.Helm
Helm doesn't have these bugs. I rendered the vendored Bitnami subcharts (
mariadb-galera-13.2.7,postgresql-16.1.0,keycloak-25.2.0,nginx-20.0.2) with DBRepo's values for them and read the probes:mysqld-exportersidecars usehttpGet /on the metrics port.dashboard-dband the Keycloakauth-dbusepg_isready.tcpSocketfor liveness andhttpGet /for readiness. Unrelated to this PR: indata-deployment.yaml,consumer-deployment.yamlandmetadata-deployment.yaml, thelivenessProbecalls/actuator/health/readinessand thereadinessProbecalls/actuator/health/liveness, so they appear to be swapped. I left that out of this PR.