# ── Stage 1: install dependencies ────────────────────────────────────────── FROM node:lts-alpine AS deps RUN apk add --no-cache libc6-compat WORKDIR /app COPY package.json package-lock.json* ./ RUN npm install --legacy-peer-deps # ── Stage 2: build the Next.js app ────────────────────────────────────────── FROM node:lts-alpine AS builder WORKDIR /app # Create non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -S nextjs -u 1001 # Copy source and deps COPY --chown=nextjs:nodejs . . COPY --from=deps --chown=nextjs:nodejs /app/node_modules ./node_modules # Remove yarn.lock so nothing accidentally invokes yarn RUN rm -f yarn.lock # Ensure data dir is writable at runtime RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data && chmod 755 /app/data # Build the app at image build time (not at container start) USER nextjs ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 RUN npm run build # ── Stage 3: production runner ─────────────────────────────────────────────── FROM node:lts-alpine AS runner RUN apk add --no-cache curl WORKDIR /app RUN addgroup -g 1001 -S nodejs && \ adduser -S nextjs -u 1001 # Copy only what's needed to run COPY --from=builder --chown=nextjs:nodejs /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json COPY --from=builder --chown=nextjs:nodejs /app/next.config.js ./next.config.js RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data && chmod 755 /app/data USER nextjs EXPOSE 3000 ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 HEALTHCHECK --interval=1m --timeout=3s CMD curl -f http://localhost:3000/ || exit 1 CMD NEXT_PUBLIC_SITE_DOMAIN=$site_domain \ NEXT_PUBLIC_FORCE_DEFAULT_THEME=$force_default_theme \ NEXT_PUBLIC_DEFAULT_SOURCE_LANG=$default_source_lang \ NEXT_PUBLIC_DEFAULT_TARGET_LANG=$default_target_lang \ npm start