Containerize Product service (multi-stage Dockerfile, /health & /ready, env config)#79
Containerize Product service (multi-stage Dockerfile, /health & /ready, env config)#79devin-ai-integration[bot] wants to merge 2 commits into
Conversation
…y, env config, .dockerignore
🤖 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:
|
| HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ | ||
| CMD curl -fsS http://localhost:5004/health || exit 1 |
There was a problem hiding this comment.
🔍 Docker HEALTHCHECK only tests liveness, not database connectivity
The Dockerfile HEALTHCHECK hits /health, which is configured with Predicate = _ => false — meaning no actual health checks run and it always returns 200 as long as the process is alive. Database connectivity is only checked via /ready. This is a valid liveness-vs-readiness separation for Kubernetes, but in plain Docker or docker-compose (which is what this repo uses), there's no built-in readiness concept. Docker will mark the container as 'healthy' even if the database is completely unreachable. If the intent is for depends_on with condition: service_healthy to gate on DB availability, this HEALTHCHECK won't accomplish that.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Intentional — the container HEALTHCHECK targets liveness (/health) on purpose. Docker uses the healthcheck for restart/replacement decisions, so gating it on DB reachability would flap the container unhealthy (and risk restart loops) during transient DB outages even though the process is fine. DB reachability is exposed separately via /ready for orchestrators that support readiness gating. Compose here doesn't use depends_on: condition: service_healthy, so there's no behavioral regression; leaving the separation in place.
Summary
Containerizes the Product service and adds proper liveness/readiness probes with fully externalized config.
Services/Product/Product.API/Dockerfile):sdk:10.0build stage (restore csproj → publish) + slimaspnet:10.0runtime stage. Runs as the non-root$APP_UIDuser, declares aHEALTHCHECKthat curls/health, and sets config only via env (ASPNETCORE_URLS=http://+:5004,ASPNETCORE_ENVIRONMENT=Production).Program.cs:/health— liveness,Predicate = _ => false(no dependency checks, 200 while the process serves requests)./ready— readiness, runs only checks taggedready; aAddDbContextCheck<ProductDbContext>reports DB reachability (200 when reachable, 503 otherwise). The old/healthzmapping is replaced.appsettings.json(wasHost=localhost;...;Password=postgres). The connection string now comes only fromConnectionStrings__DefaultConnection(already supplied bydocker-compose.yml)..dockerignoreatsrc/(the compose build context) excludingbin/,obj/,.git/, IDE files, and local.env/config so they never enter the image.Verification
dotnet build -c Releasesucceeds.docker build -f Services/Product/Product.API/Dockerfile .builds; container reports(healthy).curl /health→200 Healthy.curl /ready→503with no DB,200 Healthywhen a reachable Postgres is provided viaConnectionStrings__DefaultConnection.Note: the
..\..\Shared\*project references (unused at runtime) remain as-is — they're a repo-wide convention shared by all services and build with only a warning; left unchanged to keep this PR scoped to containerization.Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/b51bc93741e946fcbf6a6061c22462e3
Requested by: @mbatchelor81