From 753cb7ef9f00dae97a3b568a55ea76ef73b3bdb9 Mon Sep 17 00:00:00 2001 From: Daniel Padrino Date: Wed, 15 Jul 2026 12:41:22 -0300 Subject: [PATCH] fix(docker): run node under tini instead of npm to silence shutdown noise Every container stop (each release deploy + every restart) logs npm's 5-line 'command failed / signal SIGTERM' ERROR block - npm watching its child die is pure noise, ~80 blocks/week across prd+dev. tini as PID 1 forwards SIGTERM to node, which exits immediately exactly as it did under npm (the app has no shutdown hooks; stop behavior is byte-identical). Bare node as PID 1 was NOT an option: with no SIGTERM handler and PID-1 signal semantics it would ignore the signal and be SIGKILLed after the grace period, slowing every deploy. start:prod wraps nothing but the node invocation (no pre/post hooks, no npm env consumed anywhere in src/) - verified before inlining it. --- Dockerfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3555ef5b97..bac4472dac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,12 @@ RUN echo "$GIT_COMMIT" > dist/version.txt FROM node:20-alpine +# tini as PID 1: forwards SIGTERM to node so stops behave exactly as they did +# under npm (immediate exit), without npm's 5-line error block on every stop. +# Bare node as PID 1 would IGNORE SIGTERM (no handler + PID-1 semantics) and +# get SIGKILLed after the grace period instead. +RUN apk add --no-cache tini + USER node WORKDIR /home/node @@ -45,4 +51,6 @@ COPY --from=builder /home/node/assets ./assets EXPOSE 3000 -CMD ["npm", "run", "start:prod"] +ENTRYPOINT ["/sbin/tini", "--"] +# Mirrors package.json start:prod — keep the two in sync. +CMD ["node", "--max-old-space-size=6144", "dist/src/main"]