fix(compose): add working healthcheck for the graphile GraphQL server

Context

The server (PostGraphile/graphile) service in docker-compose.yml currently has no healthcheck at all — Docker/Compose/Portainer orchestration has no automated way to detect whether the GraphQL API is actually serving.

Why a naive fix doesn't work

Adding curl -f http://localhost:5678/graphql (a natural first attempt) fails for two independent reasons in this image:

  1. Dockerfile.graphile is built on node:20-alpine with no curl/wget installed — only node.
  2. Even with curl available, localhost resolves to ::1 (IPv6) first in the container's /etc/hosts, but the server only binds IPv4 (0.0.0.0:5678) — the healthcheck would still fail with "connection refused".

Fix

Uses node -e (always present in this image) to GET http://127.0.0.1:5678/graphql (explicit IPv4). That route is the lightweight landing page defined in src/server.ts (app.get('/graphql', ...)), which always returns 200 — cheaper to poll on an interval than the POST-only /v1/graphql API route itself.

healthcheck:
  test: ["CMD", "node", "-e", "require('http').get('http://127.0.0.1:5678/graphql',res=>process.exit(res.statusCode===200?0:1)).on('error',()=>process.exit(1))"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 60s

How this was found

A community-maintained Portainer stack for a production g1v2 deployment had independently added a curl -f http://localhost:5678/graphql healthcheck, which failed continuously (3+ days, unhealthy status) for the two reasons above — even though the GraphQL API itself was serving live production traffic correctly the whole time (confirmed via container logs showing hundreds of successful client requests, and by querying the API directly).

Since the upstream compose file ships no healthcheck for this service at all, anyone adding one manually is likely to hit the same two pitfalls. Proposing this fix upstream so future deployments (and this one, once it can pull the change) get a healthcheck that actually works out of the box.

Testing

Reproduced and validated against the live production container before and after:

  • Before: curl -f http://localhost:5678/graphqlcurl: not found; wget http://localhost:5678/... → connection refused (IPv6). docker inspect health log: ExitCode: 1 on every check.
  • After (this fix, applied manually to the running container's equivalent stack and redeployed): node -e ... against 127.0.0.1:5678/graphqlSTATUS 200, exit 0. Container health went from unhealthy (3 day failing streak) to healthy, confirmed stable over multiple check cycles (FailingStreak: 0).

Diagnosed and proposed with the assistance of an AI coding agent (Claude, Anthropic). Reviewed and validated by the deployment owner against a live container before submission.

Merge request reports

Loading