Containerize ApiGateway: hardened image + health/ready endpoints#80
Containerize ApiGateway: hardened image + health/ready endpoints#80devin-ai-integration[bot] wants to merge 1 commit into
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
||
| // Liveness: process is up; no dependency checks. | ||
| app.MapHealthChecks("/health", new HealthCheckOptions { Predicate = _ => false }); | ||
| app.MapHealthChecks("/healthz", new HealthCheckOptions { Predicate = _ => false }); |
There was a problem hiding this comment.
🔍 Behavioral change: /healthz endpoint now skips all registered health checks
Previously, /healthz was mapped without options (app.MapHealthChecks("/healthz")) which means it would run ALL registered health checks. The new code at src/ApiGateway/Program.cs:16 uses Predicate = _ => false, which skips all checks and always returns Healthy.
Right now this is a no-op difference because builder.Services.AddHealthChecks() at line 8 registers no actual checks. However, if someone later adds a health check (e.g., a downstream service probe), /healthz will silently ignore it. This is likely intentional given the comments, but it's a contract change on an existing endpoint that other infrastructure (e.g., Kubernetes liveness probes) may already depend on.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Intentional. /healthz is deliberately kept as a liveness alias (Predicate = _ => false) alongside the new /health (liveness) and /ready (readiness) split, following the fleet convention across the other services in this repo. Liveness probes should reflect only "is the process up" and must not gate on dependency checks — otherwise a transient downstream blip would cause liveness restart loops. Any future dependency probes should be tagged ready and will surface via /ready, which is the endpoint orchestrators/LBs should use for readiness gating. No registered checks change behavior today (none are registered), so this is a no-op now and the intended contract going forward.
Summary
Containerizes the
ApiGateway(YARP reverse proxy) into a hardened, self-contained image and adds standard liveness/readiness probes. Scoped to the gateway only — no other services touched.ApiGateway/Dockerfile— replaced the plain SDK-build/aspnet-run Dockerfile with a hardened multi-stage build:ApiGateway.csproj(no project refs) beforedotnet publish.USER $APP_UID(uid 1654).apt-get install curlin the runtime stage (not in the aspnet base image) to back theHEALTHCHECK.HEALTHCHECKtargets/health(liveness), not/ready, to avoid restart loops on dependency blips.5000(ASPNETCORE_URLS=http://+:5000); remap externally with-p.ApiGateway/Program.cs— split the single/healthzmapping into three probes:No DbContext / EF Core health check added — this is a stateless proxy, not a data service.
/healthzkept as a liveness alias for fleet consistency.src/.dockerignore(new, at build-context root) — excludesbin/,obj/, secrets, and other artifacts so stale local builds never poison the image.Downstream cluster addresses in
appsettings.json(http://identity-service:5001/, etc.) are compose DNS names, not secrets — left as-is. The existingapi-gatewaycompose block already matches (context., dockerfileApiGateway/Dockerfile, port 5000) — verified, no edit needed.Verification
dotnet build ApiGateway/ApiGateway.csproj -c Release— succeeds.docker build— image builds.docker run(no DB):/health→ 200 Healthy,/ready→ 200 Healthy,/healthz→ 200 Healthy.docker inspecthealth status →healthy.docker exec ... id→uid=1654(app)(non-root).docker compose config— valid.Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/48ee2b9dc84d49bc97a29fbe1901ff34
Requested by: @mbatchelor81