mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: unified Docker image with GPU auto-detection (#37)
Merge CPU, CUDA, and lite Docker images into a single unified image. One tag (latest) works on all platforms: amd64 (NVIDIA CUDA) and arm64 (CPU). GPU auto-detected at runtime. All ML models and packages baked in. Key changes: - Platform-conditional Dockerfile (nvidia/cuda on amd64, node on arm64) - tini as PID 1 for proper signal handling - Fix FILES_STORAGE_PATH data loss bug - Fix RealESRGAN upscaler (was broken, always fell back to Lanczos) - Fix PaddleOCR language codes and stdout corruption - Simplified CI/CD (single build, single tag) - Expanded model pre-download with verification - Shutdown timeout, improved health endpoint - Remove unused lama-cleaner
This commit is contained in:
+33
-6
@@ -23,6 +23,14 @@ import { teamsRoutes } from "./routes/teams.js";
|
||||
import { registerToolRoutes } from "./routes/tools/index.js";
|
||||
import { userFileRoutes } from "./routes/user-files.js";
|
||||
|
||||
// Warn about deprecated STIRLING_VARIANT env var
|
||||
if (process.env.STIRLING_VARIANT) {
|
||||
console.warn(
|
||||
`WARNING: STIRLING_VARIANT="${process.env.STIRLING_VARIANT}" is set but ignored. ` +
|
||||
"There is now a single unified image with all features. Remove STIRLING_VARIANT from your environment.",
|
||||
);
|
||||
}
|
||||
|
||||
// Run before anything else
|
||||
runMigrations();
|
||||
console.log("Database initialized");
|
||||
@@ -108,12 +116,23 @@ await teamsRoutes(app);
|
||||
// API docs (Scalar)
|
||||
await docsRoutes(app);
|
||||
|
||||
// Public health check (minimal - no internal details)
|
||||
app.get("/api/v1/health", async () => ({
|
||||
status: "healthy",
|
||||
version: APP_VERSION,
|
||||
variant: process.env.STIRLING_VARIANT === "lite" ? "lite" : "full",
|
||||
}));
|
||||
// Public health check (checks core dependencies)
|
||||
app.get("/api/v1/health", async (_request, reply) => {
|
||||
let dbOk = false;
|
||||
try {
|
||||
db.select().from(schema.settings).limit(1).get();
|
||||
dbOk = true;
|
||||
} catch {
|
||||
/* db unreachable */
|
||||
}
|
||||
|
||||
const status = dbOk ? "healthy" : "unhealthy";
|
||||
const code = dbOk ? 200 : 503;
|
||||
return reply.code(code).send({
|
||||
status,
|
||||
version: APP_VERSION,
|
||||
});
|
||||
});
|
||||
|
||||
// Admin health check (full diagnostics)
|
||||
app.get("/api/v1/admin/health", async (request, reply) => {
|
||||
@@ -161,12 +180,19 @@ try {
|
||||
}
|
||||
|
||||
// Graceful shutdown
|
||||
const SHUTDOWN_TIMEOUT_MS = 8000;
|
||||
let shuttingDown = false;
|
||||
async function shutdown(signal: string) {
|
||||
if (shuttingDown) return;
|
||||
shuttingDown = true;
|
||||
console.log(`\n${signal} received, shutting down gracefully...`);
|
||||
|
||||
const forceExit = setTimeout(() => {
|
||||
console.error("Shutdown timed out, forcing exit");
|
||||
process.exit(1);
|
||||
}, SHUTDOWN_TIMEOUT_MS);
|
||||
forceExit.unref();
|
||||
|
||||
cleanupCron.stop();
|
||||
|
||||
try {
|
||||
@@ -199,6 +225,7 @@ async function shutdown(signal: string) {
|
||||
console.error("Error closing database:", err);
|
||||
}
|
||||
|
||||
clearTimeout(forceExit);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user