はじめに
PrismaとDockerを使用してデータベース環境を構築していた際に、P1001 Can't reach database serverエラーが発生しました。
今回は、その原因と解決方法についてまとめます。
この記事は個人的なアウトプットを目的として作成したものです。そのため、誤った情報や不足している内容が含まれている可能性があります。もし間違いや気になる点がございましたら、ぜひご指摘いただけますと幸いです。
現象
以下のような構成で環境を作成していました。
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model Todo {
id Int @id @default(autoincrement())
title String
completed Boolean @default(false)
}
DATABASE_URL="postgresql://hoge:password@localhost:5432/mydb"
version: "3.8"
services:
client:
build: ./frontend
container_name: client
ports:
- "5173:5173"
depends_on:
- api
volumes:
- ./frontend:/app
- /app/node_modules
api:
build: ./backend
container_name: api
ports:
- "3000:3000"
volumes:
- ./backend:/app
- /app/node_modules
db:
image: postgres:16
container_name: db
environment:
POSTGRES_USER: hoge
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
ports:
- "5432:5432"
この状態でnpx prisma migrateを実行すると、以下のエラーが発生しました。
P1001 Can't reach database server at `localhost:51214` Please make sure your database server is running at `localhost:51214`.
原因
原因は、DATABASE_URLにlocalhostを指定していたことでした。
処理の流れは以下のようになります。
-
Prismaは api コンテナ内で実行される -
PrismaはDATABASE_URLを参照して接続先を決定する -
localhostを指定すると、api コンテナ自身を参照する -
しかし
PostgreSQLは db コンテナで起動している -
そのため、データベースに接続できずエラーになる
つまり、localhostは「ホストPC」ではなく「その処理が動いているコンテナ自身」を指してしまうのが原因でした。
なお、エラーメッセージに表示されている51214はPostgreSQLやPrismのデフォルトポートではなく、環境変数が正しく読み取れなかった際に表示される内部的なポート番号です。
解決方法
DATABASE_URLの接続先を、PostgreSQLが動いている db コンテナ名に変更します。
DATABASE_URL="postgresql://hoge:password@db:5432/mydb"
終わりに
ローカル開発ではあまり意識しない部分ですが、「どこから、どこへ接続しているのか」を理解することで、Docker の仕組みが一段深く理解できるエラーだと感じました。
参考