Ship prebuilt Prisma client so the server never runs prisma generate

prisma generate needs over three minutes on the production host, which made
every deploy hang on that build step. The client is now generated on the dev
machine into prisma-client.tar.gz (tracked, 8.5MB) and the image just untars
it. Dropping the unused linux-musl engine target halves that payload.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-08 16:35:06 +03:30
co-authored by Cursor
parent aa9b3ee451
commit d5dfd6a0f0
7 changed files with 49 additions and 12 deletions
+1
View File
@@ -2,6 +2,7 @@
* *
!deploy-bundle.tar.gz !deploy-bundle.tar.gz
!prisma-client.tar.gz
!Dockerfile !Dockerfile
!docker-compose.yml !docker-compose.yml
!docker-entrypoint.sh !docker-entrypoint.sh
+9 -4
View File
@@ -9,15 +9,20 @@ COPY deploy-bundle.tar.gz /tmp/deploy-bundle.tar.gz
RUN tar -xzf /tmp/deploy-bundle.tar.gz -C /app \ RUN tar -xzf /tmp/deploy-bundle.tar.gz -C /app \
&& rm /tmp/deploy-bundle.tar.gz && rm /tmp/deploy-bundle.tar.gz
# هیچ دستور prisma یا npm روی سرور اجرا نمی‌شود؛ همه چیز از قبل ساخته آمده است
ENV CHECKPOINT_DISABLE=1 ENV CHECKPOINT_DISABLE=1
ENV DO_NOT_TRACK=1
ENV PRISMA_HIDE_UPDATE_MESSAGE=1 ENV PRISMA_HIDE_UPDATE_MESSAGE=1
# اسکیما و generate قبل از dist بمانند تا لایه‌شان کش شود؛ generate روی سرور کند است
COPY package.json package-lock.json prisma.config.ts /app/ COPY package.json package-lock.json prisma.config.ts /app/
COPY prisma /app/prisma COPY prisma /app/prisma
# DATABASE_URL فقط برای بارگذاری prisma.config.ts لازم است، اتصالی برقرار نمی‌شود
RUN DATABASE_URL="postgresql://build:build@localhost:5432/build?schema=public" \ # کلاینت Prisma روی سیستم دولوپر با scripts/pack-prisma-client.sh ساخته می‌شود
./node_modules/.bin/prisma generate COPY prisma-client.tar.gz /tmp/prisma-client.tar.gz
RUN rm -rf /app/node_modules/.prisma/client \
&& mkdir -p /app/node_modules/.prisma \
&& tar -xzf /tmp/prisma-client.tar.gz -C /app/node_modules/.prisma \
&& rm /tmp/prisma-client.tar.gz
# dist آخر باشد تا دیپلوی معمولی فقط همین لایه را دوباره بسازد # dist آخر باشد تا دیپلوی معمولی فقط همین لایه را دوباره بسازد
COPY dist /app/dist COPY dist /app/dist
+11 -7
View File
@@ -27,15 +27,16 @@ npm run start:dev
## دیپلوی: بیلد روی سیستم خودت، اجرا روی سرور ## دیپلوی: بیلد روی سیستم خودت، اجرا روی سرور
روی سرور هیچ `npm` یا دانلودی لازم نیست. `node_modules` از قبل داخل روی سرور هیچ `npm` و هیچ دستور `prisma` اجرا نمی‌شود. سه چیز از قبل ساخته و روی
`deploy-bundle.tar.gz` (روی گیت) است و `dist` هم روی گیت commit می‌شود. گیت هستند: `dist`، `prisma-client.tar.gz` (کلاینت Prisma) و
`deploy-bundle.tar.gz` (`node_modules` پروداکشن).
**۱) روی سیستم خودت:** **۱) روی سیستم خودت:**
```bash ```bash
cd fabric_trade_server cd fabric_trade_server
npm run build npm run deploy:build
git add dist && git commit -m "..." && git push git add dist prisma-client.tar.gz && git commit -m "..." && git push
``` ```
**۲) روی سرور:** **۲) روی سرور:**
@@ -47,9 +48,12 @@ docker compose up -d --build
docker compose logs -f api docker compose logs -f api
``` ```
`Dockerfile` باندل را باز می‌کند، بعد `dist` و `prisma` و `package.json` را از `Dockerfile` باندل را باز می‌کند، بعد `dist` و `prisma` و کلاینت آماده‌ی Prisma
گیت روی آن می‌نویسد و `prisma generate` می‌زند؛ پس تغییر schema و مایگریشن را روی آن می‌نویسد. `prisma generate` روی هاست پروداکشن چند دقیقه طول می‌کشد،
جدید هم فقط با `git pull` می‌رسد. پس عمداً آنجا اجرا نمی‌شود.
هر بار که `prisma/schema.prisma` را عوض کردی، `npm run deploy:build` را بزن تا
`prisma-client.tar.gz` هم به‌روز شود؛ وگرنه سرور با کلاینت قدیمی بالا می‌آید.
**فقط اگر پکیج npm جدید اضافه شد** باندل را دوباره بساز و push کن: **فقط اگر پکیج npm جدید اضافه شد** باندل را دوباره بساز و push کن:
+1
View File
@@ -12,6 +12,7 @@
"start:dev": "nest start --watch", "start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch", "start:debug": "nest start --debug --watch",
"start:prod": "node dist/main.js", "start:prod": "node dist/main.js",
"deploy:build": "npm run build && bash scripts/pack-prisma-client.sh",
"build:deploy": "bash scripts/build-local-dist.sh", "build:deploy": "bash scripts/build-local-dist.sh",
"docker:dist": "docker compose -f docker-compose.dist.yml up -d --build", "docker:dist": "docker compose -f docker-compose.dist.yml up -d --build",
"test": "jest", "test": "jest",
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
generator client { generator client {
provider = "prisma-client-js" provider = "prisma-client-js"
binaryTargets = ["native", "debian-openssl-3.0.x", "linux-musl-openssl-3.0.x"] binaryTargets = ["native", "debian-openssl-3.0.x"]
} }
datasource db { datasource db {
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# کلاینت Prisma را روی سیستم دولوپر می‌سازد و بسته‌بندی می‌کند.
# سرور نباید prisma generate بزند؛ روی هاست پروडاکشن دقایق طول می‌کشد.
set -euo pipefail
cd "$(dirname "$0")/.."
OUT="prisma-client.tar.gz"
SRC="node_modules/.prisma/client"
if [ ! -d node_modules/prisma ]; then
echo "ERROR: node_modules نیست. اول npm ci بزن." >&2
exit 1
fi
# خروجی قبلی پاک شود تا engineهای بی‌استفاده در بسته نمانند
rm -rf "$SRC"
DATABASE_URL="${DATABASE_URL:-postgresql://build:build@localhost:5432/build?schema=public}" \
CHECKPOINT_DISABLE=1 ./node_modules/.bin/prisma generate
test -f "$SRC/libquery_engine-debian-openssl-3.0.x.so.node" \
|| { echo "ERROR: engine مربوط به debian-openssl-3.0.x ساخته نشد." >&2; exit 1; }
rm -f "$OUT"
tar -czf "$OUT" -C node_modules/.prisma client
ls -lh "$OUT"