Introduces scalable Docker Compose deployment

Establishes a multi-service Docker Compose setup for the application, including a Traefik reverse proxy, a MySQL database, and a scalable API service.

Adds a comprehensive MySQL database schema for bug reports, file storage, rate limiting, user management, and sessions.

Improves application startup reliability by implementing a "wait-for-MySQL" script, ensuring the API service initializes only after the database is available. This script is integrated into the Dockerfile and package.json.

Enhances the API service with instance-specific logging, a more informative health endpoint, and an increased maximum request body size (50MB). Database migration failures are now gracefully handled.
This commit is contained in:
Flavio Fois
2026-02-25 20:57:19 +01:00
parent 211ce5f1f6
commit 19e199a578
8 changed files with 178 additions and 10 deletions

View File

@@ -6,6 +6,8 @@ import { bugReportRoutes } from "./routes/bugReports";
import { adminRoutes } from "./routes/admin";
import { initLogger, Log } from "./logger";
const INSTANCE_ID = process.env.HOSTNAME + "_" + Math.random().toString(16).slice(2, 6);
// Initialize logger
initLogger();
@@ -13,7 +15,12 @@ initLogger();
validateConfig();
// Run database migrations
await runMigrations();
try {
await runMigrations();
} catch (error) {
Log("ERROR", "Failed to run migrations:", error);
process.exit(1);
}
const app = new Elysia()
.onRequest(({ request }) => {
@@ -22,7 +29,7 @@ const app = new Elysia()
request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ||
request.headers.get("x-real-ip") ||
"unknown";
Log("HTTP", `${request.method} ${url.pathname} from ${ip}`);
Log("HTTP", `[${INSTANCE_ID}] ${request.method} ${url.pathname} from ${ip}`);
})
.onAfterResponse(({ request, set }) => {
const url = new URL(request.url);
@@ -33,11 +40,13 @@ const app = new Elysia()
set.status = 500;
return { success: false, message: "Internal server error" };
})
.get("/health", () => ({ status: "ok", timestamp: new Date().toISOString() }))
.get("/health", () => ({ status: "ok", instance: INSTANCE_ID, timestamp: new Date().toISOString() }))
.get("/", () => ({ status: "ok", message: "API is running" }))
.use(bugReportRoutes)
.use(adminRoutes)
.listen({
port: config.port,
//@ts-ignore
maxBody: 50 * 1024 * 1024, // 50MB
});