Skip to content

feat: add healthchecks to Dockerfiles for api, basket, links, and uptime services#380

Merged
izadoesdev merged 1 commit intodatabuddy-analytics:stagingfrom
sekhar08:feat(docker)/add-healthchecks-to-dockerfiles
Apr 3, 2026
Merged

feat: add healthchecks to Dockerfiles for api, basket, links, and uptime services#380
izadoesdev merged 1 commit intodatabuddy-analytics:stagingfrom
sekhar08:feat(docker)/add-healthchecks-to-dockerfiles

Conversation

@sekhar08
Copy link
Copy Markdown
Contributor

@sekhar08 sekhar08 commented Apr 3, 2026

● ## Description

Add production-ready HEALTHCHECK instructions to all four service Dockerfiles, enabling Docker to natively monitor container health.

Changes:

  • api.Dockerfile — added HEALTHCHECK using shared healthcheck.ts script via bun (exec form)
  • basket.Dockerfile — switched runtime from gcr.io/distroless/cc to oven/bun:1.3.4-distroless (preserves distroless security posture), added ENTRYPOINT [] to prevent
    bun from interpreting the compiled binary as JS, added HEALTHCHECK
  • links.Dockerfile — same pattern as basket, runtime switched from gcr.io/distroless/base to oven/bun:1.3.4-distroless, port 2500
  • uptime.Dockerfile — same pattern, runtime switched from gcr.io/distroless/base to oven/bun:1.3.4-distroless, port 4000
  • healthcheck.ts — shared 3-line script that fetches /health using HEALTHCHECK_PORT env var, used by all 4 services

All health checks use exec form (CMD ["bun", "/app/healthcheck.ts"]) which works in distroless without a shell. Build stage versions are untouched.

HEALTHCHECK config: --interval=30s --timeout=3s --start-period=10s --retries=3

Checklist
  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 3, 2026

@sekhar08 is attempting to deploy a commit to the Databuddy OSS Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8eeb3850-ac70-47bc-9eaf-562df4f4f0db

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 3, 2026

Greptile Summary

This PR adds Docker native health checking to all four service Dockerfiles (api, basket, links, uptime) via a shared healthcheck.ts script, and switches the runtime base images for the compiled-binary services (basket, links, uptime) from minimal distroless variants to oven/bun:1.3.4-distroless so that bun is available to execute the TypeScript health check probe.

  • All four services already expose a /health route that returns 200 { status: "ok" }, so the probe target is valid.
  • The shared healthcheck.ts is clean and portable, but lacks a try/catch around fetch() — while Bun's unhandled-rejection behavior will still produce a non-zero exit code, explicit error handling is a safer practice.
  • ENTRYPOINT [] is correctly placed in basket, links, and uptime to prevent the bun base-image entrypoint from wrapping the compiled binary, but it is ordered after HEALTHCHECK in those files, which is unconventional.
  • api.Dockerfile, basket.Dockerfile, and uptime.Dockerfile are missing trailing newlines.
  • The HEALTHCHECK parameters (--interval=30s --timeout=3s --start-period=10s --retries=3) are reasonable defaults for all four services.

Confidence Score: 4/5

Safe to merge — all health probe targets exist, ports are correct, and the base-image switch is justified; only minor style issues remain.

The changes are additive and well-scoped. Health endpoints are verified to exist in all four services. The only functional concern (unhandled fetch rejection) still results in the correct unhealthy exit code in Bun, making it a style issue rather than a runtime bug. Missing newlines and unconventional ENTRYPOINT ordering are cosmetic. No logic errors or security regressions introduced.

healthcheck.ts — should add try/catch for explicit error handling.

Important Files Changed

Filename Overview
healthcheck.ts New shared health check script; functionally correct but lacks try/catch around fetch() for explicit error handling.
api.Dockerfile Adds HEALTHCHECK using healthcheck.ts with correct port (3001); missing trailing newline.
basket.Dockerfile Runtime switched from gcr.io/distroless/cc to oven/bun:1.3.4-distroless; ENTRYPOINT [] and HEALTHCHECK added; ENTRYPOINT ordering slightly unconventional and missing trailing newline.
links.Dockerfile Runtime switched from gcr.io/distroless/base to oven/bun:1.3.4-distroless; HEALTHCHECK added with correct port (2500); clean change.
uptime.Dockerfile Runtime switched from gcr.io/distroless/base to oven/bun:1.3.4-distroless; HEALTHCHECK added with correct port (4000); ENTRYPOINT ordering slightly unconventional and missing trailing newline.

Sequence Diagram

sequenceDiagram
    participant Docker as Docker Daemon
    participant HC as healthcheck.ts (bun)
    participant Svc as Service (/health)

    Note over Docker: Every 30s (after 10s start-period)
    Docker->>HC: exec ["bun", "/app/healthcheck.ts"]
    HC->>Svc: GET http://localhost:{HEALTHCHECK_PORT}/health
    alt HTTP 2xx
        Svc-->>HC: 200 { status: "ok" }
        HC->>Docker: exit 0 (healthy)
    else HTTP non-2xx
        Svc-->>HC: 5xx / 4xx
        HC->>Docker: exit 1 (unhealthy)
    else Connection refused / timeout
        HC->>Docker: unhandled rejection → exit 1 (unhealthy)
    end
    Note over Docker: After 3 retries unhealthy → container marked unhealthy
Loading

Reviews (1): Last reviewed commit: "feat: add healthchecks to Dockerfiles fo..." | Re-trigger Greptile

Comment on lines +2 to +3
const r = await fetch(`http://localhost:${port}/health`);
process.exit(r.ok ? 0 : 1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing error handling on fetch

fetch() can throw a network-level error (e.g., ECONNREFUSED) if the service is not yet listening. In Bun, an unhandled promise rejection does cause a non-zero exit code so the healthcheck will still be marked unhealthy — but this relies on runtime implementation details rather than explicit intent, and the error won't be surfaced in Docker logs.

A try/catch makes the failure mode explicit:

Suggested change
const r = await fetch(`http://localhost:${port}/health`);
process.exit(r.ok ? 0 : 1);
try {
const r = await fetch(`http://localhost:${port}/health`);
process.exit(r.ok ? 0 : 1);
} catch {
process.exit(1);
}

Comment on lines +40 to 44
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD ["bun", "/app/healthcheck.ts"]

ENTRYPOINT []
CMD ["./server"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 ENTRYPOINT [] placed after HEALTHCHECK

Convention is to declare ENTRYPOINT before HEALTHCHECK (and CMD) so the intended runtime contract is clear before the health probe is defined. Docker processes these as a final metadata set so this doesn't break anything, but the ordering is slightly unexpected for readers.

The same ordering applies to links.Dockerfile and uptime.Dockerfile.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

api.Dockerfile Outdated
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD ["bun", "/app/healthcheck.ts"]

CMD ["bun", "run", "src/index.ts"] No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing newline at end of file

api.Dockerfile (and also basket.Dockerfile and uptime.Dockerfile) are missing a trailing newline. Most editors and git diff flag this, and it can cause minor issues with some tooling that concatenates Dockerfiles.

@izadoesdev
Copy link
Copy Markdown
Member

Healthcheck concept is solid — all services have /health endpoints and the shared healthcheck.ts is clean.

A few things to address:

  1. Needs rebaseapi.Dockerfile on staging now uses turbo prune (3-stage build). This PR is based on the old version and will conflict. Please rebase against staging and retarget the PR there.

  2. Base image tradeoff — switching basket/links/uptime from gcr.io/distroless to oven/bun:1.3.4-distroless increases image size since you need bun to run the healthcheck script. Worth noting that an alternative is to skip in-container HEALTHCHECK for the compiled-binary services and monitor /health externally (reverse proxy, orchestrator, etc.) — which is what feat(docker): add self-hosting support with docker-compose configuration #375's compose file already suggests in its comments.

  3. ENTRYPOINT [] — correct and necessary given the bun-distroless base, just want to confirm this is intentional and tested.

Please retarget to staging — we don't merge directly to main.

@izadoesdev izadoesdev changed the base branch from main to staging April 3, 2026 21:35
@izadoesdev izadoesdev force-pushed the feat(docker)/add-healthchecks-to-dockerfiles branch from 98c780c to ba1427e Compare April 3, 2026 21:37
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@izadoesdev izadoesdev merged commit 13f0ac3 into databuddy-analytics:staging Apr 3, 2026
7 of 11 checks passed
@izadoesdev izadoesdev mentioned this pull request Apr 5, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants