Migrate to Docker: containerize for docker-server deployment

- Add Dockerfile + cron.js (daily 4pm UTC loop replacing EC2 cron)
- Add infra/docker-compose.yml and deploy-stack.sh for Portainer
- Support DATA_DIR env var in bot.js for persistent history volume
- Support PROMPTS_JSON env var in cron.js (no SSH needed for config)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 17:15:18 -07:00
parent ab32ef4cc2
commit dacc7604cc
8 changed files with 277 additions and 1 deletions

49
cron.js Normal file
View File

@@ -0,0 +1,49 @@
import { execFileSync } from "child_process";
import { writeFileSync } from "fs";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
const __dirname = dirname(fileURLToPath(import.meta.url));
const PROMPT_NAME = process.env.PROMPT_NAME;
if (!PROMPT_NAME) {
console.error("PROMPT_NAME env var required");
process.exit(1);
}
// Write prompts.json from env var.
// Future: if PROMPTS_URL is set, fetch from S3 or similar instead.
if (process.env.PROMPTS_JSON) {
writeFileSync(join(__dirname, "prompts.json"), process.env.PROMPTS_JSON);
console.log(`[${PROMPT_NAME}] Wrote prompts.json from PROMPTS_JSON env var`);
} else {
console.error("PROMPTS_JSON env var required");
process.exit(1);
}
function msUntilNext4pmUTC() {
const now = new Date();
const next = new Date(now);
next.setUTCHours(16, 0, 0, 0);
if (next <= now) next.setUTCDate(next.getUTCDate() + 1);
return next - now;
}
function runScheduler() {
console.log(`[${PROMPT_NAME}] Running scheduler at ${new Date().toISOString()}`);
try {
execFileSync("node", [join(__dirname, "scheduler.js"), PROMPT_NAME], { stdio: "inherit" });
} catch {
console.error(`[${PROMPT_NAME}] scheduler.js exited with error`);
}
scheduleNext();
}
function scheduleNext() {
const ms = msUntilNext4pmUTC();
const next = new Date(Date.now() + ms);
console.log(`[${PROMPT_NAME}] Next run at ${next.toISOString()}`);
setTimeout(runScheduler, ms);
}
scheduleNext();