<details>
<summary>Questions answered in this page</summary>

- How to run Prisma in Docker containers?
- How to configure Docker Compose with Prisma?
- How to handle migrations in Docker?

</details>

This guide walks you through setting up a Prisma ORM application within a Docker environment. You'll learn how to configure a Node.js project, integrate Prisma for database management, and orchestrate the application using Docker Compose. By the end, you'll have a fully functional Prisma application running in a Docker container.

## Prerequisites

- [Docker](https://docs.docker.com/) and [Docker Compose](https://docs.docker.com/compose/) installed
- Node.js version: A [compatible Node.js version](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#minimum-supported-nodejs-versions), required for Prisma 6.  

:::warning

Prisma 7.0.0 has updated minimum Node.js requirements:
- Node.js 20: >= 20.19.0
- Node.js 22: >= 22.12.0  
- Node.js 24: >= 24.0.0+

If you're using Prisma 7.0.0 or higher with Docker, ensure your application's Docker base image uses Node.js 22 or 24. Update your Dockerfile to use `node:22-alpine` or `node:24-alpine` instead of older Node.js 20 images.

:::

Before starting, ensure that no PostgreSQL services are running locally, and that the following ports are free to avoid conflicts: `5432` (PostgreSQL), `3000` (application server) or `5555` (Prisma Studio server).

To stop existing PostgreSQL services, use:

```terminal
sudo systemctl stop postgresql  # Linux
brew services stop postgresql   # macOS
net stop postgresql             # Windows (Run as Administrator)
```

To stop all running Docker containers and free up ports:

```terminal
docker ps -q | xargs docker stop
```

## 1. Set up your Node.js and Prisma application

Let's start by creating a simple Node.js application with Prisma ORM and [Express.js](https://expressjs.com/).

### 1.1. Initialize your project

First, create a new project directory and initialize a Node.js project:

```terminal
mkdir docker-test
cd docker-test
npm init -y 
```

This will generate a `package.json` file:

```json file=package.json
{
  "name": "docker-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {},
  "keywords": [],
  "author": "",
  "license": "ISC"
}
```

### 1.2. Install required dependencies

Next, install the Prisma CLI as a development dependency and Express.js for the server:

```terminal
npm install prisma @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg pg dotenv express
```

:::info

If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](/orm/overview/databases/database-drivers).

:::

### 1.3. Set up Prisma ORM

Now, initialize Prisma to generate the necessary files:

```terminal
npx prisma init --output ../generated/prisma
```

This creates:  

- A `prisma` folder containing `schema.prisma`, where you will define your database schema.  
- An `.env` file in the project root, which stores environment variables.  

Add a `User` model to the `schema.prisma` file located in the `prisma/schema.prisma` folder:

```prisma file=prisma/schema.prisma
datasource db {
  provider = "postgresql"
}

generator client {
  provider = "prisma-client"
  //add-start
  output = "../generated/prisma_client"
  //add-end
}

//add-start
model User {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  email     String   @unique
  name      String?
}
//add-end
```

:::note

In the `schema.prisma` file, we specify a [custom `output` path](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) where Prisma will generate its types. This ensures Prisma's types are resolved correctly across different package managers and can be accessed by application consistently inside the container without any permission issues. In this guide, the types will be generated in the `./generated/prisma_client` directory.

:::

Now, create a `prisma.config.ts` file in the root of your project:

```typescript file=prisma.config.ts
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';

export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: {
    path: 'prisma/migrations',
  },
  datasource: {
    url: env('DATABASE_URL'),
  },
});
```

:::note

You'll need to install the `dotenv` package to load environment variables:

```bash
npm install dotenv
```

:::

### 1.4. Create an Express.js server

With the Prisma schema in place, let's create an Express.js server to interact with the database. Start by creating an `index.js` file:

```terminal
touch index.js
```

Add the following code to set up a basic Express server:

```js file=index.js
//add-start
const express = require("express");
const { PrismaClient } = require("./generated/prisma_client/client");
const { PrismaPg } = require("@prisma/adapter-pg");

const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL,
});

const app = express();
const prisma = new PrismaClient({
  adapter,
});
app.use(express.json());

// Get all users
app.get("/", async (req, res) => {
  const userCount = await prisma.user.count();
  res.json(
    userCount == 0
      ? "No users have been added yet."
      : "Some users have been added to the database."
  );
});

const PORT = 3000;

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});
//add-end
```

Update the `package.json` scripts to include commands for running the server and deploying migrations:

```json file=package.json
"scripts": {
  //delete-start
  "test": "echo \"Error: no test specified\" && exit 1",
  //delete-end
  //add-start
  "dev": "node index.js",
  "db:deploy": "npx prisma migrate deploy && npx prisma generate"
  //add-end
}
```

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

To perform database migrations, we'll create a standalone PostgreSQL database using Docker Compose.

### 2.1. Create a Docker Compose file for PostgreSQL

Create a `docker-compose.postgres.yml` file in the root directory:

```yml file=docker-compose.postgres.yml
// add-start
version: '3.7'

services:
  postgres:
    image: postgres:15
    restart: always
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=prisma
    ports:
      - "5432:5432"
    networks:
      - prisma-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U prisma -d postgres"]
      interval: 5s
      timeout: 2s
      retries: 20
    volumes:
      - postgres_data:/var/lib/postgresql/data
    command: postgres -c listen_addresses='*'
    logging:
      options:
        max-size: "10m"
        max-file: "3"

networks:
  prisma-network:

volumes:
  postgres_data:
// add-end
```

### 2.2. Start the PostgreSQL container

Run the following command to start the database:

```terminal
docker compose -f docker-compose.postgres.yml up -d
```

### 2.3. Perform database migrations

With the database running, update the `.env` file with the following database connection url:

```.env file=.env
// edit-next-line
DATABASE_URL="postgresql://postgres:prisma@localhost:5432/postgres?schema=public"
```

Run the migration to create the database schema:

```terminal
npx prisma migrate dev --name init
```

Then generate Prisma Client:

```terminal
npx prisma generate
```

This should generate a `migrations` folder in the `prisma` folder and the Prisma Client in the `generated/prisma_client` directory.

### 2.4. Test the application

Start the server and verify it works:

```termial
npm run dev
```

Visit [`http://localhost:3000`](http://localhost:3000) to see the message:

```terminal
No users have been added yet.
```

Stop the local server.

### 2.5. Clean up the standalone database

Once testing is complete, remove the standalone PostgreSQL container:

```terminal
docker compose -f docker-compose.postgres.yml down --remove-orphans
```

This command will:

- Stop running containers.
- Remove containers.
- Remove the default network created by Docker Compose.
- Remove associated volumes (if not named explicitly).

Now that we've tested the application locally, let's containerize it using Docker.

## 3. Run the app and database together with Docker Compose

We'll now containerize the application using Docker, ensuring it can run in any environment.
 
To do that create a `Dockerfile` in project root:

```terminal
touch Dockerfile
```

For the next step, you'll need to choose between two options for the base image: `node:alpine` (lightweight) or `node:slim` (stable). Both options are fully supported by Prisma ORM, but may have to be configured differently.

### 3.1. Option 1: Use Linux Alpine (`node:alpine`) as a base image

The node:alpine image is based on Alpine Linux, a lightweight Linux distribution that uses the `musl` C standard library. It's perfect if you want to keep your container small and efficient. Prisma supports Alpine on `amd64` out of the box, and supports it on `arm64` since `prisma@4.10.0`.

Add the following content to the `Dockerfile`:

```shell file=Dockerfile
FROM node:lts-alpine3.17

WORKDIR /usr/src/app

COPY package.json package-lock.json ./

RUN npm ci

COPY . .

CMD ["sh", "-c", "npm run db:deploy && npm run dev"]
```

:::note

When running on Linux Alpine, Prisma downloads engines that are compiled for the `musl` C standard library. Please don't install `glibc` on Alpine (e.g., via the `libc6-compat` package), as that would prevent Prisma from running successfully.

:::

Related Docker images:

- `node:lts-alpine`
- `node:16-alpine`
- `node:14-alpine`

### 3.1. Option 2: Use Linux Debian (`node:slim`) as a base image

The `node:slim` image is based on Linux Debian, a stable and widely supported distribution that uses the `glibc` C standard library. It is mostly supported out of the box on `amd64` and `arm64`, making it a good choice if you're running into compatibility issues with Alpine or need a more production-ready environment. However, some older versions of this image may come without `libssl` installed, so it's sometimes necessary to install it manually.

Add the following content to the `Dockerfile`:

```shell file=Dockerfile
FROM node:slim

RUN apt-get update -y \
&& apt-get install -y openssl

WORKDIR /usr/src/app

COPY package.json package-lock.json ./

RUN npm ci

COPY . .

CMD ["sh", "-c", "npm run db:deploy && npm run dev"]
```

Related Docker images:

- `node:lts-slim`
- `node:bullseye-slim`
- `node:buster-slim`
- `node:stretch-slim`

### 3.2. Create and configure a Docker Compose file

Now that the `Dockerfile` is ready, we'll use Docker Compose to manage both the app and the database together. This makes it easy to start, stop, and manage the entire setup.

Create a `docker-compose.yml` file in your project folder:

```terminal
touch docker-compose.yml
```

Add the following configuration to the file:

```yml file=docker-compose.yml
// add-start
version: '3.7'

services:
  postgres_db:
    image: postgres:15
    hostname: postgres_db
    container_name: postgres_db
    restart: always
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: prisma
    ports:
      - '5432:5432'
    networks:
      - prisma-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
      interval: 5s
      timeout: 2s
      retries: 20

  server:
    build: 
      context: .  
      dockerfile: Dockerfile
    ports:
      - '3000:3000'
    stdin_open: true
    tty: true  # Keeps the container running for debugging
    depends_on:
      postgres_db:
        condition: service_healthy
    env_file:
      - .env.prod
    networks:
      - prisma-network
networks:
  prisma-network:
    name: prisma-network
// add-end
```

### 3.3. Configure environment variable for the container 

Before running the app, we need to configure the environment variables. Create a `.env.prod` file:

```
touch .env.prod
```

Add the following database connection url to the `.env.prod` file:

```.env file=.env.prod
// edit-next-line
DATABASE_URL="postgresql://postgres:prisma@postgres_db:5432/postgres?schema=public"
```

### 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:

```terminal
docker compose -f docker-compose.yml up --build -d
```

Visit `http://localhost:3000` to see your app running with the message:

```terminal
No users have been added yet.
```

### 3.5. Bonus: Add Prisma Studio for database management

[Prisma Studio](/orm/tools/prisma-studio) offers a graphical user interface (GUI) that allows you to view and manage your database directly in the browser. It's a great tool for debugging and managing your data during development.

To add Prisma Studio to your Docker setup, update the `docker-compose.yml` file:

```yml file=docker.compose.yml
version: '3.7'

services:
  postgres_db:
    image: postgres:15
    hostname: postgres_db
    container_name: postgres_db
    restart: always
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: prisma
    ports:
      - '5432:5432'
    networks:
      - prisma-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
      interval: 5s
      timeout: 2s
      retries: 20

  server:
    build: 
      context: .  
      dockerfile: Dockerfile
    ports:
      - '3000:3000'
    stdin_open: true
    tty: true  # Keeps the container running for debugging
    depends_on:
      postgres_db:
        condition: service_healthy
    env_file:
      - .env.prod
    networks:
      - prisma-network
  // add-start
  prisma-studio:
    image: node:lts-alpine3.17
    working_dir: /usr/src/app
    volumes:
      - .:/usr/src/app
    command: npx prisma studio --port 5555 --browser none
    ports:
      - "5555:5555"
    env_file:
      - .env.prod
    networks:
      - prisma-network
    depends_on:
      postgres_db:
        condition: service_healthy
      server:
        condition: service_started
    // add-end
networks:
  prisma-network:
    name: prisma-network
```

This will start Prisma Studio at [`http://localhost:5555`](http://localhost:5555) alongside the main app at [`http://localhost:3000`](http://localhost:3000). You can use Prisma Studio to manage your database with a GUI.

Run the following command to start everything:

```terminal
docker compose -f docker-compose.yml up --build -d
```

By following this guide, you've successfully containerized your Prisma app and database using Docker Compose.

---

# How to use Prisma ORM and Prisma Postgres in a pnpm workspaces monorepo