############################################ # BASE IMAGE ############################################ FROM node:20-bookworm-slim AS base # Prevent interactive prompts ENV DEBIAN_FRONTEND=noninteractive # Install minimal runtime deps needed by Prisma / Node RUN apt-get update && apt-get install -y \ openssl \ ca-certificates \ dumb-init \ && rm -rf /var/lib/apt/lists/* WORKDIR /app ############################################ # DEPENDENCIES (cached layer) ############################################ FROM base AS deps COPY package.json package-lock.json* ./ # Deterministic install RUN npm ci ############################################ # BUILDER ############################################ FROM base AS builder COPY --from=deps /app/node_modules ./node_modules COPY . . ENV NEXT_TELEMETRY_DISABLED=1 # Generate Prisma client BEFORE build RUN npx prisma generate # Build standalone NextJS output RUN npm run build ############################################ # RUNNER (VERY SMALL) ############################################ FROM base AS runner ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 ENV PORT=3000 ENV HOSTNAME=0.0.0.0 WORKDIR /app ############################################ # Copy standalone server ############################################ COPY --from=builder --chown=node:node /app/.next/standalone ./ # Static assets COPY --from=builder --chown=node:node /app/.next/static ./.next/static COPY --from=builder --chown=node:node /app/public ./public # Prisma files for CLI access COPY --from=builder --chown=node:node /app/node_modules/.prisma ./node_modules/.prisma COPY --from=builder --chown=node:node /app/node_modules/@prisma ./node_modules/@prisma COPY --from=builder --chown=node:node /app/node_modules/prisma ./node_modules/prisma COPY --from=builder --chown=node:node /app/node_modules/.bin ./node_modules/.bin # Copy dependencies needed for seed script COPY --from=builder --chown=node:node /app/node_modules/bcryptjs ./node_modules/bcryptjs COPY --from=builder --chown=node:node /app/prisma ./prisma COPY --from=builder --chown=node:node /app/package.json ./package.json # Copy entrypoint script COPY --chown=node:node docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh ############################################ # Use built-in hardened node user ############################################ USER node EXPOSE 3000 ############################################ # Auto-run migrations on startup ############################################ ENTRYPOINT ["dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]