If you use pnpm and Prisma inside a multi-stage Docker build, you might see a strange thing: Prisma tries to download its binary files (like linux-musl-openssl-3.0.x) again, even though you ran pnpm prisma generate in an earlier stage.
This is a common issue. It is not a mistake in your code. It is a problem with how Prisma checks its files and how Docker handles time when copying files.
ðŠĪ The Problem: The Timestamp Trap
Prisma is built to check if its Client is old (or "stale").
-
Prisma's Rule: Prisma checks the last modified time (timestamp) of two important files:
- Your
schema.prismafile (the source code). - The generated Prisma Client in
node_modules/.prisma/client.
- Your
-
The Decision: If the
schema.prismafile's time is newer than the Client's time, Prisma decides that the Client is old. -
The Action: It automatically runs
prisma generateagain. This action includes checking and downloading the binary files you listed inbinaryTargets.
How Docker Creates This Problem
- Builder Stage (Time T1 - Old Time): You run
pnpm prisma generate. The generated Client gets a timestamp of T1. - Runner Stage (Time T2 - New Time):
- You copy the Client from the builder:
COPY --from=builder ... .prisma. This Client keeps the old T1 timestamp. -
The Trap: You copy your
schema.prismafile from your local computer:COPY ./prisma /app/prisma. This new file gets a timestamp of T2 (the time the Docker layer is built).
- You copy the Client from the builder:
Result: When you run pnpm prisma migrate deploy, Prisma sees that T2 (schema) is newer than T1 (Client). It thinks the Client is outdated and runs generate, which causes the binary to be downloaded again.
ðĄ Three Ways to Fix This
The best solutions prevent Prisma from making this "new vs. old" comparison.
Solution 1 (The Best Way): Do Not Copy the Source Schema
The prisma migrate deploy command does not need the schema.prisma file itself. It only needs the migration files inside the migrations folder.
Change the runner stage:
FROM base AS runner
WORKDIR /app
# Copy the built Prisma Client (needed for your application or seeders)
COPY --from=builder /app/node_modules/.prisma /app/node_modules/.prisma
# â
CORRECT: Only copy the migration files
COPY ./prisma/migrations /app/prisma/migrations
# â REMOVE THIS LINE: This is the problem file!
# COPY ./prisma /app/prisma
Why it works: Prisma cannot check the timestamp if the schema.prisma file is not in the final image.
Solution 2: Copy the Full node_modules from the Builder
If your builder stage successfully generated the client, copying the entire node_modules folder (which includes the client) from that stage might help ensure that all files within that folder have consistent timestamps from T1.
Change the runner stage:
FROM base AS runner
WORKDIR /app
# â
Copy the whole node_modules, which now includes the generated client from T1.
COPY --from=builder /app/node_modules /app/node_modules
# You still need to use Solution 1 and avoid copying the schema file!
COPY ./prisma/migrations /app/prisma/migrations
# ...
Solution 3 (Quick Fix): Tell Prisma to Skip the Check
You can use an Environment Variable to make Prisma ignore the time check and assume the binary is already there.
Add this line to your runner stage:
FROM base AS runner
WORKDIR /app
ENV PRISMA_SKIP_BINARY_CHECK=1
# ... other COPY commands ...
Note: This is fast, but if your builder stage ever fails to download the binary, this fix will hide the real error until the program starts.
Top comments (0)