# syntax=docker/dockerfile:1.6 # --------------------------------------------------------------- # IPAM — Dockerfile multi-stage # --------------------------------------------------------------- # Build arg : # DATABASE_PROVIDER = sqlite (défaut) | postgresql # Rappel : le provider Prisma est statique dans schema.prisma, on # le bascule via scripts/switch-db-provider.mjs avant `prisma generate`. # --------------------------------------------------------------- ARG DATABASE_PROVIDER=sqlite # ---------- Stage 1 : deps ---------- FROM node:20-alpine AS deps RUN apk add --no-cache libc6-compat WORKDIR /app COPY package.json package-lock.json* ./ # `npm ci` exige un package-lock.json ; sinon on retombe sur `npm install` # qui en générera un. Cela permet un build « out of the box » même sans lock. RUN if [ -f package-lock.json ]; then \ npm ci; \ else \ echo "package-lock.json absent -> npm install" && \ npm install --no-audit --no-fund; \ fi # ---------- Stage 2 : build ---------- FROM node:20-alpine AS builder ARG DATABASE_PROVIDER ENV DATABASE_PROVIDER=${DATABASE_PROVIDER} # Valeur factice pour que Zod ne rejette pas la config à la génération ENV DATABASE_URL="file:./data/build-placeholder.db" WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # Bascule le provider Prisma si nécessaire, puis génère le client et build RUN node scripts/switch-db-provider.mjs "$DATABASE_PROVIDER" \ && npx prisma generate \ && npm run build # ---------- Stage 3 : runner ---------- FROM node:20-alpine AS runner ARG DATABASE_PROVIDER ENV DATABASE_PROVIDER=${DATABASE_PROVIDER} ENV NODE_ENV=production ENV PORT=3000 ENV HOSTNAME=0.0.0.0 WORKDIR /app # Outils système utiles à la découverte et à l'entrypoint : # - iputils : ping ICMP (cap_net_raw requis côté compose) # - iproute2 : `ip neigh` pour le scanner ARP # - netcat-openbsd : attente de PostgreSQL (entrypoint) # - openssl, tini, dumb-init : init + signaux propres RUN apk add --no-cache iputils iproute2 netcat-openbsd tini openssl # User non-root pour la sécurité RUN addgroup --system --gid 1001 nodejs \ && adduser --system --uid 1001 nextjs # Binaires app (mode standalone Next) COPY --from=builder --chown=nextjs:nodejs /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static # Prisma : schema + client généré + migrations (pour `migrate deploy` au boot) COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma COPY --from=builder --chown=nextjs:nodejs /app/node_modules/.prisma ./node_modules/.prisma COPY --from=builder --chown=nextjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma COPY --from=builder --chown=nextjs:nodejs /app/node_modules/prisma ./node_modules/prisma # tsx + dépendances pour pouvoir exécuter prisma/seed.ts si RUN_SEED=true COPY --from=builder --chown=nextjs:nodejs /app/node_modules/tsx ./node_modules/tsx COPY --from=builder --chown=nextjs:nodejs /app/node_modules/esbuild ./node_modules/esbuild # Entrypoint COPY --chown=nextjs:nodejs docker/entrypoint.sh /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh # Volume SQLite (inutile en PG mais inoffensif) RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data VOLUME ["/app/data"] USER nextjs EXPOSE 3000 # Healthcheck simple — retourne 200 dès que Next répond HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1 # tini pour gérer SIGTERM proprement ENTRYPOINT ["/sbin/tini", "--", "/app/entrypoint.sh"]