FROM node:20-alpine AS base # Install dependencies only when needed FROM base AS deps RUN apk add --no-cache libc6-compat WORKDIR /app # Install dependencies COPY package.json package-lock.json* ./ RUN npm install # Generate Prisma Client COPY prisma ./prisma/ RUN npx prisma generate # Rebuild the source code only when needed FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # Ensure public directory exists RUN mkdir -p public # Next.js telemetry ENV NEXT_TELEMETRY_DISABLED=1 RUN npm run build # Production image, copy all the files and run next FROM base AS runner WORKDIR /app ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 # Install Docker CLI for spawning provisioning containers RUN apk add --no-cache docker-cli RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs # Add nextjs user to docker group for socket access # Note: The actual docker group GID might differ - using 999 as common default RUN addgroup -g 999 docker || true RUN addgroup nextjs docker || true # Create jobs and logs directories for provisioning RUN mkdir -p /app/jobs /app/logs RUN chown -R nextjs:nodejs /app/jobs /app/logs # Create public directory and copy contents if they exist RUN mkdir -p public COPY --from=builder /app/public/. ./public/ # Set the correct permission for prerender cache RUN mkdir .next RUN chown nextjs:nodejs .next # Automatically leverage output traces to reduce image size COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static # Copy Prisma (client, CLI, and config) COPY --from=deps /app/node_modules/.prisma ./node_modules/.prisma COPY --from=deps /app/node_modules/@prisma ./node_modules/@prisma COPY --from=deps /app/node_modules/prisma ./node_modules/prisma COPY --from=deps /app/node_modules/.bin/prisma ./node_modules/.bin/prisma COPY prisma ./prisma/ USER nextjs EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" CMD ["node", "server.js"]