A health check that opens a TCP connection reports healthy for a process that is listening and cannot serve a request.
# almost useless: nginx accepts the connection whether or
# not php-fpm is alive
healthcheck:
test: ["CMD", "nc", "-z", "localhost", "80"]
# useful: an endpoint that touches what the app needs
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost/health"]
# and the endpoint itself checks the database connection,
# the cache, and nothing that is slow or external.
The rule that has held up is that a health check should test the dependencies the process cannot start without and nothing else. Including a third-party API makes the container unhealthy when somebody else has an outage, which turns their incident into a restart loop in yours. Including a slow query makes the check itself a load source. A readiness endpoint returning a JSON object with per-dependency status is worth building once and reusing.