diff --git a/Dockerfile b/Dockerfile index 1cfc5cb..1185ada 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,16 @@ -# Base image pulled from the Nexus mirror (direct path, no /repository/ prefix). -# Override for a local build: --build-arg NODE_IMAGE=node:20-alpine ARG NODE_IMAGE=mirror.soroushasadi.com/node:20-alpine # --------------------------------------------------------------------------- -# 1. Dependencies — installs node_modules and compiles the better-sqlite3 -# native addon (needs python3 + a C++ toolchain). +# 1. Builder — installs deps (including native better-sqlite3 compilation) +# then produces the standalone Next.js server bundle. # --------------------------------------------------------------------------- -FROM ${NODE_IMAGE} AS deps +FROM ${NODE_IMAGE} AS builder WORKDIR /app -RUN apk add --no-cache python3 make g++ ca-certificates -# .npmrc points npm at the Nexus npm-group; NPM_TOKEN (optional) authenticates. -# The token is appended at build time only — never reaches the runner image. + +# libc6-compat: needed by Next.js SWC binaries on Alpine. +# python3 / make / g++: needed to compile better-sqlite3 native addon. +RUN apk add --no-cache libc6-compat python3 make g++ ca-certificates + ARG NPM_TOKEN="" COPY package.json package-lock.json .npmrc ./ RUN if [ -n "$NPM_TOKEN" ]; then \ @@ -18,22 +18,19 @@ RUN if [ -n "$NPM_TOKEN" ]; then \ fi \ && npm ci -# --------------------------------------------------------------------------- -# 2. Builder — produces the standalone Next.js server bundle. -# --------------------------------------------------------------------------- -FROM ${NODE_IMAGE} AS builder -WORKDIR /app ENV NEXT_TELEMETRY_DISABLED=1 -COPY --from=deps /app/node_modules ./node_modules COPY . . RUN npm run build # --------------------------------------------------------------------------- -# 3. Runner — minimal runtime image. Content DB + uploads live in /data, -# which is a mounted volume so they survive image rebuilds. +# 2. Runner — minimal image. Standalone server + static assets only. +# Content DB + uploads live in /data (mounted volume). # --------------------------------------------------------------------------- FROM ${NODE_IMAGE} AS runner WORKDIR /app + +RUN apk add --no-cache libc6-compat ca-certificates + ENV NODE_ENV=production \ NEXT_TELEMETRY_DISABLED=1 \ PORT=3000 \ @@ -42,21 +39,19 @@ ENV NODE_ENV=production \ RUN addgroup -g 1001 nodejs && adduser -u 1001 -G nodejs -h /home/nextjs -D nextjs -# Standalone server, static assets, and the public/ tree (portfolio art etc.). COPY --from=builder /app/.next/standalone ./ -COPY --from=builder /app/.next/static ./.next/static -COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/static ./.next/static +COPY --from=builder /app/public ./public -# Native module + its loaders. Next's file tracing usually copies these, but -# we copy the compiled .node and bindings explicitly as a safety net. -COPY --from=builder /app/node_modules/better-sqlite3 ./node_modules/better-sqlite3 -COPY --from=builder /app/node_modules/bindings ./node_modules/bindings -COPY --from=builder /app/node_modules/file-uri-to-path ./node_modules/file-uri-to-path +# Native addon compiled in builder on Alpine/musl — copy explicitly as a +# safety net in case file tracing misses the .node binary. +COPY --from=builder /app/node_modules/better-sqlite3 ./node_modules/better-sqlite3 +COPY --from=builder /app/node_modules/bindings ./node_modules/bindings +COPY --from=builder /app/node_modules/file-uri-to-path ./node_modules/file-uri-to-path RUN mkdir -p /data/uploads && chown -R nextjs:nodejs /data /app USER nextjs VOLUME ["/data"] EXPOSE 3000 - CMD ["node", "server.js"]