fix: ensure graceful shutdown and container stop when stopApp is called (#5494)

* fix: graceful shutdown handling for backend app

* chore: add startup delay to health check script
This commit is contained in:
Mir Arif Hasan 2025-10-21 19:39:39 +06:00 committed by GitHub
parent 6064186d30
commit cd084ebbb3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 17 additions and 5 deletions

View file

@ -8,6 +8,14 @@ curlCheck() {
fi fi
} }
# Wait for initial startup period to avoid unnecessary error logs
# Check if the container has been running for at least 15 seconds
UPTIME=$(awk '{print int($1)}' /proc/uptime)
if [ "$UPTIME" -lt 15 ]; then
echo "Container still starting up (uptime: ${UPTIME}s), skipping health check..."
exit 0
fi
if [ "$ENABLE_SUBPATH_BASED_ACCESS" = "true" ]; then if [ "$ENABLE_SUBPATH_BASED_ACCESS" = "true" ]; then
curlCheck "http://localhost:${HOPP_AIO_ALTERNATE_PORT:-80}/backend/ping" || exit 1 curlCheck "http://localhost:${HOPP_AIO_ALTERNATE_PORT:-80}/backend/ping" || exit 1
else else

View file

@ -370,14 +370,16 @@ export async function isInfraConfigTablePopulated(): Promise<boolean> {
} }
/** /**
* Stop the app after 5 seconds * Stop the app after 5 seconds with graceful shutdown
* (Docker will re-start the app) * (Sends SIGTERM to trigger NestJS graceful shutdown, then Docker container stops)
*/ */
export function stopApp() { export function stopApp() {
console.log('Stopping app in 5 seconds...'); console.log('Stopping app in 5 seconds...');
setTimeout(() => { setTimeout(() => {
console.log('Stopping app now...'); console.log('Stopping app now with graceful shutdown...');
// Send SIGTERM to the current process to trigger graceful shutdown
// This will call app.close() which triggers onModuleDestroy lifecycle hooks
process.kill(process.pid, 'SIGTERM'); process.kill(process.pid, 'SIGTERM');
}, 5000); }, 5000);
} }

View file

@ -99,8 +99,10 @@ async function bootstrap() {
// Graceful shutdown // Graceful shutdown
process.on('SIGTERM', async () => { process.on('SIGTERM', async () => {
console.info('SIGTERM signal received'); console.info('SIGTERM signal received, initiating graceful shutdown...');
await app.close(); await app.close();
console.info('Application closed successfully');
process.exit(0);
}); });
} }

View file

@ -183,7 +183,7 @@ COPY aio-subpath-access.Caddyfile /etc/caddy/aio-subpath-access.Caddyfile
ENTRYPOINT [ "tini", "--" ] ENTRYPOINT [ "tini", "--" ]
COPY --chmod=755 healthcheck.sh / COPY --chmod=755 healthcheck.sh /
HEALTHCHECK --interval=2s CMD /bin/sh /healthcheck.sh HEALTHCHECK --interval=2s --start-period=15s CMD /bin/sh /healthcheck.sh
WORKDIR /dist/backend WORKDIR /dist/backend
CMD ["node", "/usr/src/app/aio_run.mjs"] CMD ["node", "/usr/src/app/aio_run.mjs"]