3 files changed
+19
-10
No files matched your search
+6
-6
@@ -38,12 +38,12 @@ COPY . .
|
|||||||
# satisfy that check; the real values are supplied at container runtime
|
# satisfy that check; the real values are supplied at container runtime
|
||||||
# via env_file (see docker-compose.local.yaml) and these are never used to
|
# via env_file (see docker-compose.local.yaml) and these are never used to
|
||||||
# connect to anything or baked into a layer that matters.
|
# connect to anything or baked into a layer that matters.
|
||||||
ENV DATABASE_HOST="localhost"
|
RUN DATABASE_HOST="localhost" \
|
||||||
ENV DATABASE_PORT="3306"
|
DATABASE_PORT="3306" \
|
||||||
ENV DATABASE_NAME="build"
|
DATABASE_NAME="build" \
|
||||||
ENV DATABASE_USER="build"
|
DATABASE_USER="build" \
|
||||||
ENV DATABASE_PASSWORD="build"
|
DATABASE_PASSWORD="build" \
|
||||||
RUN npm run build
|
npm run build
|
||||||
|
|
||||||
FROM node:22-alpine AS runner
|
FROM node:22-alpine AS runner
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const EXTENSION_MIME_TYPES: Record<string, string> = {
|
|||||||
export const MEDIA_MAX_UPLOAD_BYTES = Number(process.env.MEDIA_MAX_UPLOAD_BYTES ?? 5_000_000);
|
export const MEDIA_MAX_UPLOAD_BYTES = Number(process.env.MEDIA_MAX_UPLOAD_BYTES ?? 5_000_000);
|
||||||
|
|
||||||
/** Overridable so a non-Docker deployment can point this somewhere else; defaults to a directory next to the app, outside public/. */
|
/** Overridable so a non-Docker deployment can point this somewhere else; defaults to a directory next to the app, outside public/. */
|
||||||
const MEDIA_ROOT = path.resolve(process.env.MEDIA_STORAGE_ROOT || path.join(process.cwd(), "storage", "media"));
|
const MEDIA_ROOT = path.resolve(process.env.MEDIA_STORAGE_ROOT || path.join(/* turbopackIgnore: true */ process.cwd(), "storage", "media"));
|
||||||
|
|
||||||
export const MEDIA_URL_PREFIX = "/api/media/";
|
export const MEDIA_URL_PREFIX = "/api/media/";
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ function containerName(slug: string) {
|
|||||||
return `nextchair-${slug}`;
|
return `nextchair-${slug}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function healthState(value: string | undefined): BusinessStatus["health"] {
|
||||||
|
return value === "healthy" || value === "unhealthy" || value === "starting" ? value : "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
async function readRegistry(): Promise<BusinessDeployment[]> {
|
async function readRegistry(): Promise<BusinessDeployment[]> {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(await fs.readFile(registryPath(), "utf8")) as BusinessDeployment[];
|
return JSON.parse(await fs.readFile(registryPath(), "utf8")) as BusinessDeployment[];
|
||||||
@@ -36,7 +40,7 @@ async function inspectContainer(slug: string) {
|
|||||||
try {
|
try {
|
||||||
const result = await docker(["inspect", "-f", "{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{end}}", containerName(slug)]);
|
const result = await docker(["inspect", "-f", "{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{end}}", containerName(slug)]);
|
||||||
const [container, health] = result.stdout.trim().split("|");
|
const [container, health] = result.stdout.trim().split("|");
|
||||||
return { container: container === "running" ? "running" : container ? "stopped" : "unknown", health: health || "unknown" } as const;
|
return { container: container === "running" ? "running" : container ? "stopped" : "unknown", health: healthState(health) } as const;
|
||||||
} catch {
|
} catch {
|
||||||
return { container: "unknown", health: "unknown" } as const;
|
return { container: "unknown", health: "unknown" } as const;
|
||||||
}
|
}
|
||||||
@@ -54,8 +58,13 @@ async function databaseStatus() {
|
|||||||
async function storageBytes(slug: string) {
|
async function storageBytes(slug: string) {
|
||||||
try {
|
try {
|
||||||
const volume = await docker(["volume", "inspect", "-f", "{{.Mountpoint}}", `nextchair-media-${slug}`]);
|
const volume = await docker(["volume", "inspect", "-f", "{{.Mountpoint}}", `nextchair-media-${slug}`]);
|
||||||
const usage = await run("du", ["-sk", volume.stdout.trim()], { maxBuffer: 1024 * 64 });
|
const mountpoint = volume.stdout.trim();
|
||||||
return Number.parseInt(usage.stdout.trim().split(/\s+/)[0], 10) * 1024;
|
if (!mountpoint) return null;
|
||||||
|
const usage = await run("du", ["-sk", mountpoint], { maxBuffer: 1024 * 64 });
|
||||||
|
const kilobytes = usage.stdout.trim().split(/\s+/)[0];
|
||||||
|
if (!kilobytes) return null;
|
||||||
|
const bytes = Number.parseInt(kilobytes, 10) * 1024;
|
||||||
|
return Number.isFinite(bytes) ? bytes : null;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user