fix: reap HEALTHCHECK zombies by running tini as PID 1#4252
Open
JamBalaya56562 wants to merge 1 commit intoDokploy:canaryfrom
Open
fix: reap HEALTHCHECK zombies by running tini as PID 1#4252JamBalaya56562 wants to merge 1 commit intoDokploy:canaryfrom
JamBalaya56562 wants to merge 1 commit intoDokploy:canaryfrom
Conversation
Node.js as PID 1 does not reap children it did not spawn, so the HEALTHCHECK curl fired every 10s accumulates as <defunct>. Install tini and set it as ENTRYPOINT so any orphaned child is reaped while signals still reach Node.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a running Dokploy host (v0.29.0),
[curl] <defunct>zombies accumulate inside the container — over a hundred observed after several days. Their parent is the Node.jspnpm startprocess running as PID 1.Root cause
Dockerfile's finalCMDrunsexec pnpm start, making Node.js PID 1 inside the container.HEALTHCHECKspawnscurlevery 10s in the same PID namespace.child_process; it installs no genericwaitpidreaper. Any process parented to PID 1 by the container runtime stays<defunct>until PID 1 exits.Grepping the repo confirms no Node code invokes
curlviachild_process, so the image'sHEALTHCHECKis the sole runtime source. This is the well-known "Node.js as PID 1" containerization pitfall.Fix
Install
tini(already in Debian, ~28 KB) and set it asENTRYPOINT. It reaps orphaned children regardless of origin while still forwarding signals (SIGTERM/SIGINT) to Node — the same mechanismdocker run --inituses internally.The
HEALTHCHECKis preserved unchanged: it is still useful as a Swarm rolling-update readiness gate and fordocker psoperator visibility. With tini in place its curl children are reaped.Only the main
Dockerfileis modified.Dockerfile.cloud,Dockerfile.schedule, andDockerfile.serverdeclare noHEALTHCHECKand are out of scope.Testing
Built the image locally and verified:
/usr/bin/tini --versionreportstini version 0.19.0.tini.docker exec -d; zombie count after 3s was0.HEALTHCHECKfire for 65s (6 cycles, Postgres absent so the check fails as expected); zombie count was0.docker stopterminated the container promptly, confirming signal forwarding works.Greptile Summary
This PR fixes zombie process accumulation (
[curl] <defunct>) caused by Node.js running as PID 1 and failing to reap HEALTHCHECKcurlchildren. It installstiniviaapt-getand sets it asENTRYPOINT, delegating PID 1 reaping duties to tini while leaving the existingHEALTHCHECK,CMD, and all other image contents unchanged.Confidence Score: 5/5
Safe to merge — the fix is minimal, correct, and well-tested; no behaviour changes beyond zombie reaping and signal forwarding.
Only one file is touched with two small changes: adding
tinito an existingapt-getline and replacing a bareCMDwith a properENTRYPOINT+CMDpair. The approach (tini as PID 1 init) is the canonical Docker solution for this problem,/usr/bin/tiniis the correct Debian Bookworm path, and the--separator is used correctly. No logic, API, or schema changes are involved.No files require special attention.
Reviews (1): Last reviewed commit: "fix: reap HEALTHCHECK zombies by running..." | Re-trigger Greptile