Docker 中的 NestJS 无法在另一个 Docker 容器中的 Postgres 上执行 Prisma Migrate
Posted
技术标签:
【中文标题】Docker 中的 NestJS 无法在另一个 Docker 容器中的 Postgres 上执行 Prisma Migrate【英文标题】:NestJS in Docker can't do a Prisma Migrate on Postgres in another Docker Container 【发布时间】:2021-06-11 09:41:54 【问题描述】:我在为通过 Prisma 与已在另一个容器中运行的 Postgress 数据库通信的 NestJS 应用程序创建 Docker 映像时遇到问题。 问题是在 Docker Build 的“prisma generate”阶段无法访问数据库。
这是简短的版本。 :-)
docker-compose 数据库
首先,数据库的 docker-compose 在 'docker-compose up -d' 之后运行良好:
version: '3.9'
services:
db:
image: postgres:latest
restart: "no"
container_name: hwpostgres
volumes:
- ./database:/var/lib/postgresql/data
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: root
POSTGRES_USER: root
POSTGRES_DB: taskDb
networks:
default:
external:
name: my-network
docker-compose 的 API
还有另一个构建 NestJS API 应用程序的 docker-compose 文件:
ersion: '3.9'
services:
api:
build:
context: ./build
dockerfile: Dockerfile_api
image: hwapi
restart: "no"
container_name: hwapi
environment:
DATABASE_URL: postgresql://root:root@hwpostgres:5432/tasksDb?schema=public
ports:
- "8080:3001"
command: ["node", "dist/main.js"]
networks:
default:
external:
name: cops-net
Dockerfile_api
Dockerfile_api 如下所示:
FROM node:latest As development
ARG DATABASE_URL=postgresql://root:root@hwpostgres:5432/tasksDb?schema=public
ENV DATABASE_URL $DATABASE_URL
WORKDIR /usr/src/app
COPY . .
RUN npm install -g npm@7.6.3
RUN npm install
RUN npx prisma migrate dev --name init --preview-feature
RUN npm run build
这里显示的这个 Dockerfile_api 显然是多部分 Dockerfile 的第一阶段,但第二部分对于这个问题描述并不感兴趣。
问题是“npx prisma migrate”命令失败,因为它找不到数据库。 构建过程该部分的输出:
Step 8/9 : RUN npx prisma migrate dev --name init --preview-feature
---> Running in 938d6538806a
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "tasksDb", schema "public" at "hwpostgres:5432"
Error: P1001: Can't reach database server at `hwpostgres`:`5432`
Please make sure your database server is running at `hwpostgres`:`5432`.
所以,它说数据库有问题
同样的事情交互
当我将 Dockerfile_api 更改为以下内容时:
FROM node:latest As development
ARG DATABASE_URL=postgresql://root:root@hwpostgres:5432/tasksDb?schema=public
ENV DATABASE_URL $DATABASE_URL
WORKDIR /usr/src/app
COPY . .
RUN npm install -g npm@7.6.3
RUN npm install
# RUN npx prisma migrate dev --name init --preview-feature
# RUN npm run build
并将该 Dockerfile 的 docker-compose.yml 中的命令更改为
command: ["sleep", "3650d"]
然后容器在构建完成后继续运行。
然后我进入创建的 Docker 容器(docker exec -it hwapi /bin/bash), 然后执行“npm prisma migrate”命令,一切正常!!
输出:
/usr/src/app# echo $DATABASE_URL
postgresql://root:root@hwpostgres:5432/tasksDb?schema=public
/usr/src/app# npx prisma migrate dev --name init --preview-feature
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "tasksDb", schema "public" at "hwpostgres:5432"
Already in sync, no schema change or pending migration was found.
/usr/src/app#
所以,这里看起来可以找到运行数据库的Container。
为什么在Build阶段找不到数据库,而我在同一个Container的交互式版本中进行Prisma Migrate时却可以找到数据库?
【问题讨论】:
您能否尝试将服务保存在单个撰写文件中,如 here 所示,然后检查? 【参考方案1】:诀窍在于,当您在 docker-compose 设置中运行 docker 容器时,您会在与数据库相同的 docker 网络中运行它。
当您运行 docker build
时,您不与您的数据库在同一个 docker 网络中,因此无法找到它。
就个人而言,我建议不要将迁移步骤作为映像构建的一部分运行,而是将其作为容器启动过程的一部分运行 - 可能在自定义 ENTRYPOINT
脚本中。
如果您想将迁移作为映像构建的一部分,您可以尝试运行docker build --network=my-network
,其中my-network
是您将运行数据库附加到的网络的名称。
【讨论】:
那么实际的问题是为什么在构建阶段你不在同一个 docker 网络中?那么这个“docker build”阶段是什么?显然存在许多解决方法。就像您建议的那样,将所有内容放在同一个 docker-compose 设置中(我特别不想要)。我已经尝试在 docker build 阶段之外进行数据库迁移。您的 ENTRYPOINT 建议很好,谢谢。【参考方案2】:答案也是正确的,我只是想补充一点,在我的情况下,遇到同样的问题,我只需要将图像添加到主机网络,方法是在 docker-compose.yml 文件中写入:
network_mode: "host"
然后,我们可以连接到主机数据库,然后我们可以执行脚本的其余部分。所以,总结一下,如果你不想使用 postgres 作为一个单独的图像,而是在宿主 linux 机器上,那么你可以使用提供的代码。
【讨论】:
以上是关于Docker 中的 NestJS 无法在另一个 Docker 容器中的 Postgres 上执行 Prisma Migrate的主要内容,如果未能解决你的问题,请参考以下文章
无法将 MongoDB 与 NestJS ( Docker ) 连接
无法从运行在另一个 docker 容器中的 Geoserver 连接到在 docker 中运行的 Postgis
NestJs / Mongoose 在 Docker 撰写时无法建立 MongoDB 数据库连接