Docker 中的 NestJS 无法在另一个 Docker 容器中的 Postgres 上执行 Prisma 迁移

Ber*_*rtC 5 postgresql docker docker-compose nestjs prisma

我在为 NestJS 应用程序创建 Docker 映像时遇到问题,该应用程序通过 Prisma 与已在另一个容器中运行的 Postgress 数据库进行通信。问题是在 Docker 构建的“prisma 生成”阶段无法访问数据库。

这是简短的版本。:-)

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

Run Code Online (Sandbox Code Playgroud)

API 的 docker-compose

还有另一个构建 NestJS API 应用程序的 docker-compose 文件:

version: '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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

这里显示的 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`.
Run Code Online (Sandbox Code Playgroud)

所以,它说数据库有问题

交互方式相同

当我将 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
Run Code Online (Sandbox Code Playgroud)

并将该 Dockerfile 的 docker-compose.yml 中的命令更改为

    command: ["sleep", "3650d"]
Run Code Online (Sandbox Code Playgroud)

然后容器在构建完成后继续运行。

然后我进入创建的 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#
Run Code Online (Sandbox Code Playgroud)

所以,在这里看起来它能够找到运行数据库的容器。

为什么在构建阶段找不到数据库,而在同一个容器的交互版本中进行 Prisma Migrate 时却可以找到数据库?

Tyl*_*eck 5

诀窍在于,当您在 docker-compose 设置中运行 docker 容器时,您将在与数据库相同的 docker 网络中运行它。

当您运行时docker build,您与数据库不在同一个 docker 网络内,因此它找不到它。

就个人而言,我建议不要将迁移步骤作为映像构建的一部分运行,而是将其作为容器启动过程的一部分运行 - 可能在自定义脚本中ENTRYPOINT

如果您想将迁移保留为映像构建的一部分,您可以尝试运行docker build --network=my-network,其中my-network是您将运行数据库附加到的网络的名称。