Le déploiement restait bloqué sur ENCRYPTION_KEY. J'ai tenu trop longtemps la position « pas de valeur par défaut », en confondant deux choses : refuser une clé livrée avec l'image — ce qui reste juste, une clé publiée dans un dépôt ne protège rien — et exiger qu'un humain en fabrique une avant tout démarrage. Une variable d'environnement n'est d'ailleurs pas un bon coffre : elle s'affiche dans `docker inspect` et dans l'interface de gestion. Un fichier produit au démarrage, dans un volume distinct de la base et des documents, n'est pas moins protégé — et une sauvegarde de l'un n'emporte plus la clé de l'autre. Le point d'entrée la produit donc si elle manque, l'écrit en 0600, et l'affiche une fois dans les journaux avec ce qu'il faut en faire. Une clé fournie explicitement l'emporte toujours : un déploiement qui gère ses secrets ailleurs ne doit pas être contrarié. La pile démarre désormais sans aucune variable. Éprouvé sur le script lui-même : première exécution, clé de 32 octets produite et annoncée ; deuxième, reprise en silence depuis le fichier ; avec une clé fournie, le fichier reste intact. Corrigé au passage, révélé par un échec transitoire du test : une écriture disque impossible — volume plein, droits, montage absent — remontait en exception non traitée. L'écran restait muet, la pièce n'était pas déposée et rien ne le disait. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cr9dkEHwbDgkWPnyGj1Rjv
49 lines
1.9 KiB
Docker
49 lines
1.9 KiB
Docker
# syntax=docker/dockerfile:1
|
|
|
|
FROM node:22-alpine AS base
|
|
RUN corepack enable
|
|
WORKDIR /app
|
|
|
|
# ---- dependencies -----------------------------------------------------------
|
|
FROM base AS deps
|
|
COPY package.json pnpm-lock.yaml ./
|
|
COPY prisma ./prisma
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
# ---- build ------------------------------------------------------------------
|
|
FROM base AS build
|
|
COPY --from=deps /app/node_modules ./node_modules
|
|
COPY . .
|
|
RUN pnpm db:generate && pnpm build
|
|
|
|
# ---- runtime ----------------------------------------------------------------
|
|
FROM base AS runner
|
|
ENV NODE_ENV=production
|
|
|
|
RUN addgroup --system --gid 1001 nodejs \
|
|
&& adduser --system --uid 1001 --ingroup nodejs nextjs
|
|
|
|
# `output: standalone` emits a server bundle carrying only the modules it uses.
|
|
COPY --from=build --chown=nextjs:nodejs /app/.next/standalone ./
|
|
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
COPY --from=build --chown=nextjs:nodejs /app/public ./public
|
|
|
|
# Migrations run at startup, so the image can be deployed without a separate
|
|
# migration step. prisma/ and its CLI are needed for that.
|
|
COPY --from=build --chown=nextjs:nodejs /app/prisma ./prisma
|
|
COPY --from=build --chown=nextjs:nodejs /app/node_modules/prisma ./node_modules/prisma
|
|
COPY --from=build --chown=nextjs:nodejs /app/node_modules/.bin/prisma ./node_modules/.bin/prisma
|
|
COPY --from=build --chown=nextjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma
|
|
COPY --chown=nextjs:nodejs docker/entrypoint.sh ./docker/entrypoint.sh
|
|
|
|
# Créé dans l'image, et non laissé au montage : un volume nommé hérite du
|
|
# propriétaire du répertoire qu'il recouvre, et sans cela l'application —
|
|
# qui ne tourne pas en root — ne pourrait pas y écrire.
|
|
RUN mkdir -p /data/documents /secrets && chown -R nextjs:nodejs /data /secrets
|
|
|
|
USER nextjs
|
|
EXPOSE 3000
|
|
ENV PORT=3000 HOSTNAME=0.0.0.0
|
|
|
|
CMD ["./docker/entrypoint.sh"]
|