Livrer la CLI de migration dans une disposition qui tient
Le conteneur démarrait puis s'arrêtait sur « Cannot find module '@prisma/config' ». Le Dockerfile prélevait à la main quelques répertoires de node_modules — `prisma`, `.bin/prisma`, `@prisma` — en supposant une disposition plate. pnpm range les dépendances dans un magasin virtuel `.pnpm`, sous des répertoires au nom haché : la CLI arrivait sans les siennes. Elle est désormais installée par npm, qui produit une disposition plate, copiable telle quelle. La version est lue dans package.json plutôt que figée, pour qu'elle ne diverge pas au premier changement. Tout ce qui sert aux migrations — modules, schéma, configuration — vit dans un arbre séparé. Les superposer aux modules de l'application les ferait entrer en collision : la sortie `standalone` porte `react` en lien symbolique vers le magasin pnpm, là où l'installation npm l'apporte en répertoire réel. Deux arbres n'ont rien à s'écraser. `prisma.config.ts` n'importe plus `dotenv` de façon ferme : la sortie `standalone` n'embarque que ce que le serveur utilise, et `dotenv` n'en fait pas partie — l'import aurait fait échouer les migrations au démarrage. Cette fois l'image a été reconstituée à l'identique et **démarrée** : clé produite, migrations appliquées, serveur prêt, `/connexion` en 200 et `/api/sante` rapportant `tenantIsolation: enforced`. C'est ce que j'aurais dû faire aux trois tentatives précédentes, où je n'avais éprouvé que des morceaux. La simulation a d'ailleurs trouvé un chemin `/migrator` en dur dans le point d'entrée ; il est désormais surchargeable, comme l'emplacement de la clé. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cr9dkEHwbDgkWPnyGj1Rjv
This commit is contained in:
3 files changed
+45
-9
No files matched your search
+24
-7
@@ -16,6 +16,19 @@ COPY --from=deps /app/node_modules ./node_modules
|
|||||||
COPY . .
|
COPY . .
|
||||||
RUN pnpm db:generate && pnpm build
|
RUN pnpm db:generate && pnpm build
|
||||||
|
|
||||||
|
# CLI Prisma pour les migrations au démarrage, installée à plat.
|
||||||
|
#
|
||||||
|
# `node_modules/prisma` de pnpm ne se recopie pas : ses dépendances vivent dans
|
||||||
|
# le magasin virtuel `.pnpm`, sous un répertoire au nom haché. En prélever
|
||||||
|
# quelques répertoires à la main donne une CLI qui se lance et s'arrête sur
|
||||||
|
# « Cannot find module '@prisma/config' ». npm produit une disposition plate,
|
||||||
|
# copiable telle quelle.
|
||||||
|
#
|
||||||
|
# La version est lue dans package.json : la figer ici la ferait diverger au
|
||||||
|
# premier changement.
|
||||||
|
RUN PRISMA_VERSION="$(node -p "require('/app/package.json').devDependencies.prisma")" \
|
||||||
|
&& npm install --prefix /migrator --no-save --no-audit --no-fund "prisma@${PRISMA_VERSION}"
|
||||||
|
|
||||||
# ---- runtime ----------------------------------------------------------------
|
# ---- runtime ----------------------------------------------------------------
|
||||||
FROM base AS runner
|
FROM base AS runner
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
@@ -23,17 +36,21 @@ ENV NODE_ENV=production
|
|||||||
RUN addgroup --system --gid 1001 nodejs \
|
RUN addgroup --system --gid 1001 nodejs \
|
||||||
&& adduser --system --uid 1001 --ingroup nodejs nextjs
|
&& adduser --system --uid 1001 --ingroup nodejs nextjs
|
||||||
|
|
||||||
|
# Tout ce qui sert aux migrations vit à part, dans /migrator : modules, schéma
|
||||||
|
# et fichier de configuration.
|
||||||
|
#
|
||||||
|
# Les superposer aux modules de l'application les ferait entrer en collision —
|
||||||
|
# la sortie `standalone` de pnpm porte `react` en lien symbolique vers son
|
||||||
|
# magasin interne, là où l'installation npm de la CLI l'apporte en répertoire
|
||||||
|
# réel. Deux arbres séparés n'ont rien à s'écraser.
|
||||||
|
COPY --from=build --chown=nextjs:nodejs /migrator/node_modules /migrator/node_modules
|
||||||
|
COPY --from=build --chown=nextjs:nodejs /app/prisma /migrator/prisma
|
||||||
|
COPY --from=build --chown=nextjs:nodejs /app/prisma.config.ts /migrator/prisma.config.ts
|
||||||
|
|
||||||
# `output: standalone` emits a server bundle carrying only the modules it uses.
|
# `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/standalone ./
|
||||||
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static
|
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
COPY --from=build --chown=nextjs:nodejs /app/public ./public
|
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
|
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
|
# Créé dans l'image, et non laissé au montage : un volume nommé hérite du
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ set -eu
|
|||||||
# gère ses secrets par ailleurs ne doit pas être contrarié.
|
# gère ses secrets par ailleurs ne doit pas être contrarié.
|
||||||
|
|
||||||
KEY_FILE="${ENCRYPTION_KEY_FILE:-/secrets/encryption.key}"
|
KEY_FILE="${ENCRYPTION_KEY_FILE:-/secrets/encryption.key}"
|
||||||
|
# Surchargeable pour pouvoir éprouver ce script hors d'une image.
|
||||||
|
MIGRATOR_DIR="${MIGRATOR_DIR:-/migrator}"
|
||||||
|
|
||||||
if [ -z "${ENCRYPTION_KEY:-}" ]; then
|
if [ -z "${ENCRYPTION_KEY:-}" ]; then
|
||||||
if [ -f "$KEY_FILE" ]; then
|
if [ -f "$KEY_FILE" ]; then
|
||||||
@@ -49,6 +51,12 @@ export ENCRYPTION_KEY
|
|||||||
|
|
||||||
# Les migrations s'appliquent au démarrage : l'image se déploie sans étape
|
# Les migrations s'appliquent au démarrage : l'image se déploie sans étape
|
||||||
# séparée.
|
# séparée.
|
||||||
./node_modules/.bin/prisma migrate deploy
|
#
|
||||||
|
# Depuis /migrator, arbre séparé de celui de l'application : la CLI y trouve ses
|
||||||
|
# propres dépendances, et le fichier de configuration y résout `prisma/config`.
|
||||||
|
# Appelée par son chemin plutôt que par `.bin/prisma` — un lien symbolique
|
||||||
|
# recopié d'une image à l'autre est une dépendance de plus à la disposition des
|
||||||
|
# fichiers, et c'est exactement ce qui a cassé ici.
|
||||||
|
( cd "$MIGRATOR_DIR" && node node_modules/prisma/build/index.js migrate deploy )
|
||||||
|
|
||||||
exec node server.js
|
exec node server.js
|
||||||
+12
-1
@@ -1,6 +1,17 @@
|
|||||||
import 'dotenv/config';
|
|
||||||
import { defineConfig } from 'prisma/config';
|
import { defineConfig } from 'prisma/config';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `.env` est pratique en développement, absent en conteneur — où les variables
|
||||||
|
* viennent de l'environnement et où `dotenv` n'est pas installé : la sortie
|
||||||
|
* `standalone` de Next n'embarque que ce que le serveur utilise. Un import
|
||||||
|
* ferme ferait échouer les migrations au démarrage de l'image.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
await import('dotenv/config');
|
||||||
|
} catch {
|
||||||
|
// Rien à charger : les variables sont déjà dans l'environnement.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prisma 7 moved the migration connection URL out of schema.prisma.
|
* Prisma 7 moved the migration connection URL out of schema.prisma.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in new issue
Block a user