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 \
|
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
|
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
|
USER node
|
||||||
|
|
||||||
# Next.js standalone server (node process). Plain `node server.js` — Bun is
|
# 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
|
# installed for the `docker exec` one-shot bins, not for the web runtime
|
||||||
# (Next is shipped and tested on Node).
|
# (Next is shipped and tested on Node).
|
||||||
|
ENTRYPOINT ["/bin/sh", "/docker-entrypoint.sh"]
|
||||||
CMD ["node", "server.js"]
|
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],
|
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(
|
const commandExecutors = new Map(
|
||||||
commands.map((command) => [command.builder.name, command.execute]),
|
commands.map((command) => [command.builder.name, command.execute]),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue