FROM node:20-alpine AS base WORKDIR /app RUN apk add --no-cache openssl # ---- deps: install full dependency tree (needed to build) ---- FROM base AS deps COPY package.json package-lock.json ./ COPY prisma ./prisma RUN npm ci # ---- builder: compile the Next.js app ---- FROM base AS builder # Next.js inlines NEXT_PUBLIC_* vars into the client bundle at build time, so # this has to be a build arg, not just a runtime environment variable. ARG NEXT_PUBLIC_VAPID_PUBLIC_KEY ENV NEXT_PUBLIC_VAPID_PUBLIC_KEY=$NEXT_PUBLIC_VAPID_PUBLIC_KEY COPY --from=deps /app/node_modules ./node_modules COPY . . RUN npm run build # ---- runner: production image ---- FROM base AS runner ENV NODE_ENV=production COPY package.json package-lock.json ./ COPY prisma ./prisma RUN npm ci --omit=dev COPY --from=builder /app/.next ./.next COPY --from=builder /app/public ./public COPY --from=builder /app/next.config.js ./next.config.js COPY docker/entrypoint.sh ./docker/entrypoint.sh RUN chmod +x ./docker/entrypoint.sh EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD node -e "fetch('http://localhost:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" ENTRYPOINT ["./docker/entrypoint.sh"] CMD ["npm", "start"]