# Docker & Prisma in Monorepos ## The Challenge When using Prisma in a pnpm monorepo with Docker, there's a common pitfall related to how Prisma embeds file paths. ## Understanding the Problem ### 1. Prisma Embeds Schema Paths When you run `prisma generate`, Prisma creates a client at `node_modules/.prisma/client/` and embeds the **schema path** as metadata: ```javascript // Inside generated client (simplified) const config = { schemaPath: "apps/bff/prisma/schema.prisma", // ← This path is embedded! // ... } ``` ### 2. Monorepo vs Production Directory Structures **During Build (Monorepo):** ``` /app/ ├── apps/ │ └── bff/ │ ├── prisma/schema.prisma ← Schema here │ └── src/ ├── packages/ └── pnpm-workspace.yaml ``` **In Production (After pnpm deploy):** ``` /app/ ├── prisma/schema.prisma ← Schema moved to root! ├── dist/ └── node_modules/ ``` ### 3. The Mismatch The generated Prisma client still contains: ```javascript schemaPath: "apps/bff/prisma/schema.prisma" ``` But in production, the schema is at: ``` prisma/schema.prisma ``` This causes errors like: ``` Error: Could not load `--schema` from provided path `apps/bff/prisma/schema.prisma`: file or directory not found ``` ## The Solution Regenerate the Prisma client **from the production directory layout** before creating the final image: ```dockerfile # After pnpm deploy creates the bundle at /app (final layout) WORKDIR /app RUN npx prisma@6.16.0 generate --schema=prisma/schema.prisma ``` This regenerates the client with: ```javascript schemaPath: "prisma/schema.prisma" // ← Matches production! ``` ## Best Practices ### 1. Document the Behavior Add comments in Dockerfile and schema.prisma explaining why regeneration is needed. ### 2. Version Lock Prisma Use explicit version in Docker: ```dockerfile RUN npx prisma@6.16.0 generate --schema=prisma/schema.prisma ``` ### 3. Match Prisma Versions Ensure the version in Docker matches `package.json`: ```json { "dependencies": { "@prisma/client": "^6.16.0" }, "devDependencies": { "prisma": "^6.16.0" } } ``` ### 4. Include Binary Targets Always include the production binary target in schema: ```prisma generator client { provider = "prisma-client-js" binaryTargets = ["native", "linux-musl-openssl-3.0.x"] } ``` ## Debugging ### Check Embedded Path You can inspect the generated client's config: ```bash cat node_modules/.prisma/client/index.js | grep schemaPath ``` ### Verify Schema Location In the container: ```bash ls -la /app/prisma/schema.prisma ``` ### Common Errors | Error | Cause | Fix | |-------|-------|-----| | `Could not load --schema from path` | Embedded path doesn't match actual location | Regenerate from production structure | | `Prisma Client not found` | Client not generated or not copied | Run `prisma generate` in Dockerfile | | `Query engine not found` | Missing binary target | Add correct `binaryTargets` to schema | ## Further Reading - [Prisma with pnpm](https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/prisma-client-pnpm) - [Prisma Docker Best Practices](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/deployment)