diff --git a/Dockerfile b/Dockerfile index 062e088b51..fbb7b0704e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,31 +2,19 @@ # ============================================================================== # EpicNext-CMS — Docker image (Node 26.8.1, multi-package-manager, Next.js standalone) # ============================================================================== -# Supports pnpm (default), npm, and yarn. The build stage detects which package -# manager lockfile is present and uses it automatically. -# ============================================================================== # --- Builder stage --- FROM node:26.8.1-bookworm-slim AS builder -# git is needed by next.config.ts (git rev-parse for deploymentId) and -# ca-certificates by package registries. Build runs on host network (see -# compose: iptables is disabled), so apt has registry access here. RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates \ && rm -rf /var/lib/apt/lists/* -# Install all three package managers so the build can pick whichever lockfile exists. RUN npm install -g pnpm@11.25.0 yarn WORKDIR /app -# Lockfiles and installer settings are the only inputs to the dependency layer. -# The wildcard supports pnpm-lock.yaml, package-lock.json and yarn.lock. COPY package.json *lock* pnpm-workspace.yaml .npmrc ./ -# --- Detect package manager & install dependencies --- -# Priority: pnpm > yarn > npm -# Build arg lets the user force a manager; otherwise it is auto-detected. ARG PACKAGE_MANAGER= RUN --mount=type=cache,id=epicnext-pnpm,target=/pnpm/store,sharing=locked \ @@ -44,15 +32,8 @@ RUN --mount=type=cache,id=epicnext-pnpm,target=/pnpm/store,sharing=locked \ npm install --ignore-scripts; \ fi -# Source changes invalidate compilation, but keep the installed dependencies. COPY . . -# Build only the checked out source; CI owns revision selection and freshness checks. - -# Build the production bundle. -# The .env file is loaded ONLY inside this RUN layer (not persisted as ENV, so no -# secrets end up in the image) — Next.js needs NEXT_PUBLIC_* + validated build-time -# values (HOTEL_NAME, DATABASE_URL, AUTH_SECRET, ...) at build time. ENV NODE_ENV=production RUN --mount=type=cache,id=epicnext-next,target=/app/.next/cache,sharing=locked \ if [ -f .env ]; then set -a && . ./.env && set +a; fi && \ @@ -64,31 +45,12 @@ RUN --mount=type=cache,id=epicnext-next,target=/app/.next/cache,sharing=locked \ pnpm build; \ fi -# Standalone output already contains the traced runtime dependencies. -# Pruning builder/node_modules here would not shrink the final image. - # --- Runtime stage --- FROM node:26.8.1-bookworm-slim AS runner -# Catalog Studio publishes to self-hosted Git repositories over HTTPS. -# curl is the fallback downloader for clone sources that block Node's TLS -# fingerprint (e.g. Leet.city) — see import/core/curl-fetch.ts. -# curl-impersonate ships a curl built with Chrome's exact TLS fingerprint -# (statically-linked BoringSSL; only libz/libc required). Several sources -# enable Cloudflare `cf-mitigated: challenge` against the distro curl's JA3, -# so prefer the impersonated binary at runtime (curl-fetch.ts resolves it). RUN apt-get update && apt-get install -y --no-install-recommends git curl ca-certificates \ - && mkdir -p /opt/curl-impersonate \ - && curl -fsSL "https://github.com/lwthiker/curl-impersonate/releases/download/v0.6.1/curl-impersonate-v0.6.1.x86_64-linux-gnu.tar.gz" \ - | tar -xz -C /opt/curl-impersonate \ - && chmod +x /opt/curl-impersonate/curl_chrome116 /opt/curl-impersonate/curl-impersonate-chrome \ && rm -rf /var/lib/apt/lists/* -# The CMS writes to bind-mounted host directories (/var/www/Gamedata is owned by -# the host's www-data user, UID/GID 33). The node base image already ships a -# www-data user with UID/GID 33, which matches that ownership — so we run as -# www-data and can write to the shared gamedata directory. If your host owner -# differs, override via --build-arg RUN_USER (e.g. --build-arg RUN_USER=1000). ARG RUN_USER=www-data ENV NODE_ENV=production @@ -99,25 +61,18 @@ EXPOSE 3002 WORKDIR /app -# Storage directory for runtime uploaded media (persistent volume). -# Also create the hardcoded gamedata mount point (/var/www/Gamedata is -# bind-mounted at runtime so the CMS can read + write imported assets there). RUN mkdir -p /app/storage \ /app/public/nitro-assets \ /app/public/swf \ /var/www/Gamedata \ && chown -R ${RUN_USER} /app /var/www/Gamedata -# Copy standalone Next.js output (includes a minimal node_modules). COPY --from=builder --chown=${RUN_USER} /app/.next/standalone ./ -# Copy static assets (public files served directly). COPY --from=builder --chown=${RUN_USER} /app/public ./public -# Copy the server-side static build output. COPY --from=builder --chown=${RUN_USER} /app/.next/static ./.next/static -# Client assets + runtime uploads live outside the image (mounted volumes). VOLUME ["/app/public/nitro-assets", "/app/public/swf", "/app/storage"] USER ${RUN_USER} -CMD ["node", "server.js"] \ No newline at end of file +CMD ["node", "server.js"]