From 2473c308c07084fa79f6be4365797e30cb796950 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Tue, 26 May 2026 18:56:32 +0530 Subject: [PATCH] docs: add production docker monorepo guidance --- .../content/docs/guides/deployment/docker.mdx | 50 ++++++++++++++++--- .../docs/guides/deployment/turborepo.mdx | 8 +-- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/apps/docs/content/docs/guides/deployment/docker.mdx b/apps/docs/content/docs/guides/deployment/docker.mdx index c5142d1175..e2c143337e 100644 --- a/apps/docs/content/docs/guides/deployment/docker.mdx +++ b/apps/docs/content/docs/guides/deployment/docker.mdx @@ -122,7 +122,7 @@ Now, create a `prisma.config.ts` file in the root of your project: ```typescript title="prisma.config.ts" import "dotenv/config"; -import { defineConfig, env } from "prisma/config"; +import { defineConfig } from "prisma/config"; export default defineConfig({ schema: "prisma/schema.prisma", @@ -130,7 +130,7 @@ export default defineConfig({ path: "prisma/migrations", }, datasource: { - url: env("DATABASE_URL"), + url: process.env["DATABASE_URL"], }, }); ``` @@ -198,10 +198,27 @@ Update the `package.json` scripts to include commands for running the server and "scripts": { "test": "echo \"Error: no test specified\" && exit 1", // [!code --] "dev": "node index.js", // [!code ++] - "db:deploy": "npx prisma migrate deploy && npx prisma generate" // [!code ++] + "db:generate": "npx prisma generate", // [!code ++] + "db:deploy": "npx prisma migrate deploy" // [!code ++] } ``` +Add the generated Prisma Client output to `.gitignore` and `.dockerignore`. The client is generated during the Docker image build, so it does not need to be committed or sent as part of the Docker build context: + +```text title=".gitignore" +node_modules +generated +.env +.env.* +``` + +```text title=".dockerignore" +node_modules +generated +.env +.env.* +``` + Now that the application is set up, let's move on to configuring a PostgreSQL database using Docker Compose. ## 2. Set up a PostgreSQL database with Docker Compose @@ -337,9 +354,14 @@ COPY package.json package-lock.json ./ RUN npm ci +COPY prisma ./prisma +COPY prisma.config.ts ./ + +RUN npm run db:generate + COPY . . -CMD ["sh", "-c", "npm run db:deploy && npm run dev"] +CMD ["npm", "run", "dev"] ``` :::note @@ -372,11 +394,22 @@ COPY package.json package-lock.json ./ RUN npm ci +COPY prisma ./prisma +COPY prisma.config.ts ./ + +RUN npm run db:generate + COPY . . -CMD ["sh", "-c", "npm run db:deploy && npm run dev"] +CMD ["npm", "run", "dev"] ``` +:::tip[Production migrations] + +Generate Prisma Client during the Docker image build, but run `prisma migrate deploy` separately from the long-running application container. In production, this is usually a CI/CD release step or a one-off job that runs before the new application version starts. Avoid running `migrate deploy` in the Dockerfile build because the build should not need access to your production database. + +::: + Related Docker images: - `node:lts-slim` @@ -455,10 +488,13 @@ DATABASE_URL="postgresql://postgres:prisma@postgres_db:5432/postgres?schema=publ ### 3.4. Build and run the application -With everything set up, it's time to build and run the app using Docker Compose. Run the following command: +With everything set up, build the app image, start PostgreSQL, apply pending migrations once, and then start the app: ```bash -docker compose -f docker-compose.yml up --build -d +docker compose -f docker-compose.yml build +docker compose -f docker-compose.yml up -d postgres_db +docker compose -f docker-compose.yml run --rm server npm run db:deploy +docker compose -f docker-compose.yml up -d server ``` Visit `http://localhost:3000` to see your app running with the message: diff --git a/apps/docs/content/docs/guides/deployment/turborepo.mdx b/apps/docs/content/docs/guides/deployment/turborepo.mdx index a0181517ac..37f12a2b8f 100644 --- a/apps/docs/content/docs/guides/deployment/turborepo.mdx +++ b/apps/docs/content/docs/guides/deployment/turborepo.mdx @@ -130,7 +130,7 @@ The `prisma.config.ts` file created in the `packages/database` directory should ```typescript title="packages/database/prisma.config.ts" import "dotenv/config"; -import { defineConfig, env } from "prisma/config"; +import { defineConfig } from "prisma/config"; export default defineConfig({ schema: "prisma/schema.prisma", @@ -138,14 +138,14 @@ export default defineConfig({ path: "prisma/migrations", }, datasource: { - url: env("DATABASE_URL"), + url: process.env["DATABASE_URL"], }, }); ``` :::warning -It is recommended to add `packages/database/generated` to your root `.gitignore` because generated Prisma Client code is a build artifact that can be recreated with `db:generate`. +It is recommended to add `packages/database/generated` to your root `.gitignore` because generated Prisma Client code is a build artifact that can be recreated with `db:generate`. If you build apps from this monorepo with Docker, add the same path to `.dockerignore` and run `db:generate` during the image build instead of copying generated files from your host machine. ::: @@ -306,6 +306,8 @@ If you're not using a bundler, use the [Compiled Packages](https://turborepo.dev By completing these steps, you'll make the Prisma types and `PrismaClient` instance accessible throughout the monorepo. +Export Prisma Client from the workspace package (`@repo/db`) and import that package from apps. Avoid importing the generated client with a relative path from another workspace, because that couples apps to the database package's internal folder layout and makes Docker build contexts harder to keep minimal. + ## 3. Import the `database` package in the web app The `turborepo-prisma` project should have an app called `web` at `apps/web`. Add the `database` dependency to `apps/web/package.json`: