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 数据库连接

NestJS 控制器未映射

MongooseModule:无法连接到数据库。在带有 Mongo 的 dockerized Nestjs 应用程序上

如何在 Docker 容器内观察 NestJs 应用程序中开发的文件更改