mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix: speedup docker creation by reducing steps and bunch up copy operations
This commit is contained in:
committed by
diegosouzapw
parent
af96e33184
commit
279e9c47bc
@@ -37,6 +37,8 @@ INITIAL_PASSWORD=CHANGEME
|
||||
# Base directory for all persistent data (SQLite DB, logs, backups).
|
||||
# Used by: src/lib/db/core.ts — resolves the SQLite database file path.
|
||||
# Default: ~/.omniroute/ | Override for Docker or custom installations.
|
||||
# Hint: When running in Docker, consider mounting a host directory here for data persistence across container restarts
|
||||
# also if you want to share the same database as "npm run dev" use "./data"
|
||||
# DATA_DIR=/var/lib/omniroute
|
||||
|
||||
# Encryption key for SQLite database encryption at rest.
|
||||
|
||||
51
Dockerfile
51
Dockerfile
@@ -1,10 +1,22 @@
|
||||
FROM node:24-trixie-slim AS builder
|
||||
# ── Common base with runtime deps ──────────────────────────────────────────
|
||||
FROM node:24-trixie-slim AS base
|
||||
WORKDIR /app
|
||||
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=shared \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=shared \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends libsecret-1-0 ca-certificates python3 make g++ \
|
||||
&& apt-get install -y --no-install-recommends libsecret-1-0 ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ── Builder ────────────────────────────────────────────────────────────────
|
||||
FROM base AS builder
|
||||
|
||||
# Build tools for native module compilation
|
||||
# apt-get update needed here because base's rm -rf clears the shared cache
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=shared \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=shared \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends python3 make g++ \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY package*.json ./
|
||||
@@ -26,12 +38,15 @@ RUN --mount=type=cache,target=/root/.npm \
|
||||
&& npm rebuild better-sqlite3 \
|
||||
&& node -e "require('better-sqlite3')(':memory:').close()"
|
||||
|
||||
# Use Turbopack for significant build speedup
|
||||
ENV OMNIROUTE_USE_TURBOPACK=1
|
||||
|
||||
COPY . ./
|
||||
RUN --mount=type=cache,target=/app/.next/cache \
|
||||
mkdir -p /app/data && npm run build -- --webpack
|
||||
mkdir -p /app/data && npm run build
|
||||
|
||||
FROM node:24-trixie-slim AS runner-base
|
||||
WORKDIR /app
|
||||
# ── Runner base ────────────────────────────────────────────────────────────
|
||||
FROM base AS runner-base
|
||||
|
||||
LABEL org.opencontainers.image.title="omniroute" \
|
||||
org.opencontainers.image.description="Unified AI proxy — route any LLM through one endpoint" \
|
||||
@@ -46,15 +61,11 @@ ENV NODE_OPTIONS="--max-old-space-size=256"
|
||||
|
||||
# Data directory inside Docker — must match the volume mount in docker-compose.yml
|
||||
ENV DATA_DIR=/app/data
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends libsecret-1-0 ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
RUN mkdir -p /app/data
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
# The standalone build + syncStandaloneExtraModules bundles all runtime files
|
||||
# (.next, node_modules, migrations, scripts, docs, etc.) into .next/standalone/.
|
||||
# Explicit overrides below cover modules that NFT tracing may miss.
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
# Explicitly copy @swc/helpers — not always traced by standalone output but needed at runtime
|
||||
COPY --from=builder /app/node_modules/@swc/helpers ./node_modules/@swc/helpers
|
||||
@@ -70,18 +81,6 @@ COPY --from=builder /app/node_modules/split2 ./node_modules/split2
|
||||
# traced by Next.js standalone output — copy them explicitly.
|
||||
COPY --from=builder /app/src/lib/db/migrations ./migrations
|
||||
ENV OMNIROUTE_MIGRATIONS_DIR=/app/migrations
|
||||
# MITM server.cjs is spawned at runtime via child_process — not traced by nft
|
||||
COPY --from=builder /app/src/mitm/server.cjs ./src/mitm/server.cjs
|
||||
# Runtime docs are pruned by .dockerignore to English markdown + OpenAPI.
|
||||
# Next.js standalone tracing does not include docs read via fs.
|
||||
COPY --from=builder /app/.next/standalone/docs ./docs
|
||||
|
||||
COPY --from=builder /app/scripts/dev/run-standalone.mjs ./dev/run-standalone.mjs
|
||||
COPY --from=builder /app/scripts/build/runtime-env.mjs ./build/runtime-env.mjs
|
||||
COPY --from=builder /app/scripts/build/bootstrap-env.mjs ./build/bootstrap-env.mjs
|
||||
COPY --from=builder /app/scripts/dev/healthcheck.mjs ./healthcheck.mjs
|
||||
|
||||
RUN node -e "require('better-sqlite3')(':memory:').close()"
|
||||
|
||||
# Hand /app over to the baked-in `node` non-root user (UID/GID 1000) so the
|
||||
# runtime process never holds root privileges. The chown happens after all
|
||||
|
||||
@@ -147,6 +147,18 @@ export async function syncStandaloneNativeAssets(
|
||||
sourcePath: path.join(rootDir, "node_modules", "wreq-js", "rust"),
|
||||
destinationPath: path.join(rootDir, ".next", "standalone", "node_modules", "wreq-js", "rust"),
|
||||
},
|
||||
{
|
||||
label: "better-sqlite3 native binary",
|
||||
sourcePath: path.join(rootDir, "node_modules", "better-sqlite3", "build"),
|
||||
destinationPath: path.join(
|
||||
rootDir,
|
||||
".next",
|
||||
"standalone",
|
||||
"node_modules",
|
||||
"better-sqlite3",
|
||||
"build"
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
let changed = false;
|
||||
@@ -171,6 +183,90 @@ export async function syncStandaloneNativeAssets(
|
||||
return changed;
|
||||
}
|
||||
|
||||
export async function syncStandaloneExtraModules(
|
||||
rootDir = projectRoot,
|
||||
fsImpl = fs,
|
||||
log = console
|
||||
) {
|
||||
const entries = [
|
||||
{
|
||||
label: "@swc/helpers",
|
||||
sourcePath: path.join(rootDir, "node_modules", "@swc", "helpers"),
|
||||
destRelative: path.join("node_modules", "@swc", "helpers"),
|
||||
},
|
||||
{
|
||||
label: "pino-abstract-transport",
|
||||
sourcePath: path.join(rootDir, "node_modules", "pino-abstract-transport"),
|
||||
destRelative: path.join("node_modules", "pino-abstract-transport"),
|
||||
},
|
||||
{
|
||||
label: "pino-pretty",
|
||||
sourcePath: path.join(rootDir, "node_modules", "pino-pretty"),
|
||||
destRelative: path.join("node_modules", "pino-pretty"),
|
||||
},
|
||||
{
|
||||
label: "split2",
|
||||
sourcePath: path.join(rootDir, "node_modules", "split2"),
|
||||
destRelative: path.join("node_modules", "split2"),
|
||||
},
|
||||
{
|
||||
label: "migrations",
|
||||
sourcePath: path.join(rootDir, "src", "lib", "db", "migrations"),
|
||||
destRelative: "migrations",
|
||||
},
|
||||
{
|
||||
label: "MITM server",
|
||||
sourcePath: path.join(rootDir, "src", "mitm", "server.cjs"),
|
||||
destRelative: path.join("src", "mitm", "server.cjs"),
|
||||
},
|
||||
{
|
||||
label: "run-standalone script",
|
||||
sourcePath: path.join(rootDir, "scripts", "dev", "run-standalone.mjs"),
|
||||
destRelative: path.join("dev", "run-standalone.mjs"),
|
||||
},
|
||||
{
|
||||
label: "runtime-env script",
|
||||
sourcePath: path.join(rootDir, "scripts", "build", "runtime-env.mjs"),
|
||||
destRelative: path.join("build", "runtime-env.mjs"),
|
||||
},
|
||||
{
|
||||
label: "bootstrap-env script",
|
||||
sourcePath: path.join(rootDir, "scripts", "build", "bootstrap-env.mjs"),
|
||||
destRelative: path.join("build", "bootstrap-env.mjs"),
|
||||
},
|
||||
{
|
||||
label: "healthcheck script",
|
||||
sourcePath: path.join(rootDir, "scripts", "dev", "healthcheck.mjs"),
|
||||
destRelative: "healthcheck.mjs",
|
||||
},
|
||||
{
|
||||
label: "public directory",
|
||||
sourcePath: path.join(rootDir, "public"),
|
||||
destRelative: "public",
|
||||
},
|
||||
{
|
||||
label: "playwright-core (dynamic import by gemini-web executor)",
|
||||
sourcePath: path.join(rootDir, "node_modules", "playwright-core"),
|
||||
destRelative: path.join("node_modules", "playwright-core"),
|
||||
},
|
||||
];
|
||||
|
||||
let changed = false;
|
||||
const standaloneRoot = path.join(rootDir, ".next", "standalone");
|
||||
|
||||
for (const entry of entries) {
|
||||
if (!(await exists(entry.sourcePath))) continue;
|
||||
|
||||
const destPath = path.join(standaloneRoot, entry.destRelative);
|
||||
await fsImpl.mkdir(path.dirname(destPath), { recursive: true });
|
||||
await fsImpl.cp(entry.sourcePath, destPath, { recursive: true, force: true });
|
||||
log.log(`[build-next-isolated] Synced standalone module: ${entry.label}`);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
export async function main() {
|
||||
const movedPaths = [];
|
||||
const transientBuildPaths = getTransientBuildPaths();
|
||||
@@ -225,6 +321,15 @@ export async function main() {
|
||||
nativeAssetErr
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await syncStandaloneExtraModules(projectRoot);
|
||||
} catch (extraModuleErr) {
|
||||
console.warn(
|
||||
"[build-next-isolated] Non-fatal error syncing extra modules:",
|
||||
extraModuleErr
|
||||
);
|
||||
}
|
||||
}
|
||||
process.exitCode = result.code;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user