# Multi-stage build for the ANOUMA app (Next.js + Payload CMS + WebRTC # signaling, all served by the custom server.ts — see next.config.ts for why # this can't use Next's "standalone" output). DATABASE_URI/PAYLOAD_SECRET/etc. # are only needed at *runtime*, not at build time (see docker-compose.yml and # .env.example) — this image builds without a database connection. FROM node:22-alpine AS base # ---- deps: install once, cached as its own layer ------------------------- FROM base AS deps RUN apk add --no-cache libc6-compat WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci # ---- builder: full source + production build ------------------------------ FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . ENV NEXT_TELEMETRY_DISABLED=1 RUN npm run build # ---- runner: the actual runtime image -------------------------------------- FROM base AS runner WORKDIR /app ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 RUN addgroup --system --gid 1001 nodejs \ && adduser --system --uid 1001 nextjs # Copied wholesale (not a hand-picked list of directories) so newly added # source folders (collections, scripts, lib/*, components/*, ...) are never # silently missing at runtime — .dockerignore already excludes what doesn't # belong in the image (node_modules is re-added explicitly below, .next is # the build output we do want). COPY --from=builder --chown=nextjs:nodejs /app /app # Writable at runtime, independent of the image — actual data lives in the # Docker volumes mounted over these paths (see docker-compose.yml). RUN mkdir -p media backups && chown -R nextjs:nodejs media backups USER nextjs EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME=0.0.0.0 HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ CMD node -e "fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" CMD ["npm", "start"]