feat(docker): gate Discord bot on DISCORD_TOKEN presence in container entrypoint
This commit is contained in:
parent
7e0532f43e
commit
6c97b1a41c
3 changed files with 59 additions and 0 deletions
|
|
@ -121,9 +121,12 @@ EXPOSE 3000
|
|||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||
CMD wget -qO- "http://127.0.0.1:${PORT:-3000}/api/health" >/dev/null 2>&1 || exit 1
|
||||
|
||||
COPY --chmod=755 docker-entrypoint.sh /docker-entrypoint.sh
|
||||
|
||||
USER node
|
||||
|
||||
# Next.js standalone server (node process). Plain `node server.js` — Bun is
|
||||
# installed for the `docker exec` one-shot bins, not for the web runtime
|
||||
# (Next is shipped and tested on Node).
|
||||
ENTRYPOINT ["/bin/sh", "/docker-entrypoint.sh"]
|
||||
CMD ["node", "server.js"]
|
||||
33
docker-entrypoint.sh
Executable file
33
docker-entrypoint.sh
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/sh
|
||||
# docker-entrypoint.sh — Polaris Task Force container entrypoint (PID 1).
|
||||
# Always starts the web server (CMD: node server.js, received as "$@").
|
||||
# Starts the Discord bot (`bun run bot`) ONLY when DISCORD_TOKEN is set
|
||||
# (Coolify per-environment activation gate; dev/stage leave it unset).
|
||||
# Forwards SIGTERM/SIGINT to both children, reaps them, and exits with
|
||||
# the web server's exit status.
|
||||
"$@" &
|
||||
WEB_PID=$!
|
||||
BOT_PID=""
|
||||
if [ -n "${DISCORD_TOKEN:-}" ]; then
|
||||
echo "[entrypoint] DISCORD_TOKEN is set — starting Discord bot" >&2
|
||||
bun run bot &
|
||||
BOT_PID=$!
|
||||
else
|
||||
echo "[entrypoint] DISCORD_TOKEN is not set — Discord bot disabled" >&2
|
||||
fi
|
||||
forward() {
|
||||
signal=$1
|
||||
[ -z "$WEB_PID" ] || kill -"$signal" "$WEB_PID" 2>/dev/null || true
|
||||
[ -z "$BOT_PID" ] || kill -"$signal" "$BOT_PID" 2>/dev/null || true
|
||||
}
|
||||
trap 'forward TERM' TERM
|
||||
trap 'forward INT' INT
|
||||
while kill -0 "$WEB_PID" 2>/dev/null; do
|
||||
wait "$WEB_PID"
|
||||
status=$?
|
||||
done
|
||||
if [ -n "$BOT_PID" ]; then
|
||||
kill -TERM "$BOT_PID" 2>/dev/null || true
|
||||
wait "$BOT_PID" 2>/dev/null || true
|
||||
fi
|
||||
exit "${status:-0}"
|
||||
|
|
@ -15,6 +15,29 @@ const main = async () => {
|
|||
intents: [GatewayIntentBits.Guilds],
|
||||
});
|
||||
|
||||
let shuttingDown = false;
|
||||
const shutdown = async (signal: NodeJS.Signals): Promise<void> => {
|
||||
if (shuttingDown) {
|
||||
payload.logger.warn(`[Bot] ${signal} received again — forcing exit`);
|
||||
process.exit(143);
|
||||
}
|
||||
shuttingDown = true;
|
||||
payload.logger.info(`[Bot] ${signal} received — shutting down gracefully`);
|
||||
try {
|
||||
if (client.isReady()) {
|
||||
await client.destroy();
|
||||
}
|
||||
payload.logger.info("[Bot] Discord client destroyed");
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Unknown error";
|
||||
payload.logger.error(`[Bot] Error during shutdown: ${message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
||||
process.on("SIGINT", () => void shutdown("SIGINT"));
|
||||
|
||||
const commandExecutors = new Map(
|
||||
commands.map((command) => [command.builder.name, command.execute]),
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue