# ============================================================================= # Dockerfile.nextjs — multi-stage build for the Next.js frontend # ============================================================================= # # Production-ready Docker image for Next.js with: # - Multi-stage build for minimal image size # - Standalone server output for containerized deployment # - Non-root user for security # - Health check support # # Build args (set via --build-arg or docker-compose args): # - NEXT_PUBLIC_API_URL: Public URL for the frontend (inlined at build time) # - NODE_ENV: Environment (defaults to production) # # Required: next.config.ts must have `output: "standalone"` enabled. # ============================================================================= # ── Stage 1: Dependencies ──────────────────────────────────────────────────── FROM node:20-alpine AS deps WORKDIR /app # Copy package files COPY package.json package-lock.json* ./ # Install dependencies RUN if [ -f package-lock.json ]; then \ npm ci --no-audit --no-fund; \ else \ npm install --no-audit --no-fund; \ fi # ── Stage 2: Build ─────────────────────────────────────────────────────────── FROM node:20-alpine AS builder WORKDIR /app # Copy node_modules from deps stage COPY --from=deps /app/node_modules ./node_modules # Copy source files COPY . . # Set build arguments (inlined into client bundle) ARG NEXT_PUBLIC_API_URL=http://localhost:3000 ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} ARG NODE_ENV=production ENV NODE_ENV=${NODE_ENV} # Build the Next.js application RUN npm run build # ── Stage 3: Runtime ───────────────────────────────────────────────────────── FROM node:20-alpine AS runner WORKDIR /app # Set production environment ENV NODE_ENV=production ENV PORT=3000 # Create non-root user for security RUN addgroup --system --gid 1001 nodejs \ && adduser --system --uid 1001 nextjs # Copy standalone server and static assets from builder COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/public ./public # Expose the port EXPOSE 3000 # Switch to non-root user USER nextjs # Health check HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=6 \ CMD wget -qO- http://localhost:3000/ || exit 1 # Start the standalone server CMD ["node", "server.js"]