# ========================================= # Stage 1: Install Dependencies # ========================================= # IMPORTANT: Node.js Version Maintenance # This Dockerfile uses Node.js 24.13.0-slim, which was the latest LTS version at the time of writing. # To ensure security and compatibility, regularly update the NODE_VERSION ARG to the latest LTS version. ARG NODE_VERSION=24.13.0-slim FROM node:${NODE_VERSION} AS dependencies # Set the working directory WORKDIR /app # Copy package-related files first to leverage Docker's caching mechanism COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./ # Install project dependencies with frozen lockfile for reproducible builds RUN --mount=type=cache,target=/root/.npm \ --mount=type=cache,target=/usr/local/share/.cache/yarn \ --mount=type=cache,target=/root/.local/share/pnpm/store \ if [ -f package-lock.json ]; then \ npm ci --no-audit --no-fund; \ elif [ -f yarn.lock ]; then \ corepack enable yarn && yarn install --frozen-lockfile --production=false; \ elif [ -f pnpm-lock.yaml ]; then \ corepack enable pnpm && pnpm install --frozen-lockfile; \ else \ echo "No lockfile found." && exit 1; \ fi # ============================================ # Stage 2: Build Next.js Application # ============================================ FROM node:${NODE_VERSION} AS builder # Set the working directory WORKDIR /app # Copy project dependencies from dependencies stage COPY --from=dependencies /app/node_modules ./node_modules # Copy application source code COPY . . ENV NODE_ENV=production # Next.js collects completely anonymous telemetry data about general usage. # Learn more here: https://nextjs.org/telemetry # Uncomment the following line in case you want to disable telemetry during the build. # ENV NEXT_TELEMETRY_DISABLED=1 # Build Next.js application # Cache mount speeds up subsequent builds by persisting Next.js build cache RUN --mount=type=cache,target=/app/.next/cache \ if [ -f package-lock.json ]; then \ npm run build; \ elif [ -f yarn.lock ]; then \ corepack enable yarn && yarn build; \ elif [ -f pnpm-lock.yaml ]; then \ corepack enable pnpm && pnpm build; \ else \ echo "No lockfile found." && exit 1; \ fi # ========================================= # Stage 3: Serve Static Files with serve # ========================================= FROM node:${NODE_VERSION} AS runner # Set the working directory WORKDIR /app # Install serve globally (pinned version for reproducibility, update to the latest version as needed) # Cache npm global installs to speed up builds RUN --mount=type=cache,target=/root/.npm \ npm install -g serve@14.2.5 # Set the port for serve (default is 3000) ENV PORT=3000 # Copy the static build output from the build stage COPY --from=builder --chown=node:node /app/out ./out # Use the built-in non-root user for security best practices USER node # Expose port 3000 to allow HTTP traffic EXPOSE 3000 # Start serve to serve static files # -s: serve single-page application (SPA) mode # -l: listen on specified port # -n: no clipper (don't show file listing) CMD ["serve", "-s", "out", "-l", "3000", "-n"]