You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker环境下NestJS无法连接MongoDB的问题求助

问题:Docker化NestJS应用无法连接Docker内MongoDB副本集

我有一个基于Prisma和MongoDB的NestJS应用,本地运行NestJS时能正常连接Docker化的MongoDB,但将NestJS部署到Docker容器后,无法连接MongoDB。

相关配置文件

1. docker-compose.yml

version: '3.8'

services:
  # Replica Set (required for Prisma Client)
  mongo:
    container_name: mongo
    build:
      dockerfile: ./docker/mongo.Dockerfile
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: prisma
      MONGO_REPLICA_HOST: 127.0.0.1
      MONGO_REPLICA_PORT: 27018
    env_file:
      - .env
    ports:
      - '27018:27018'
  web:
    build:
      dockerfile: ./docker/app.Dockerfile
    environment:
      DATABASE_URL: mongodb://root:prisma@mongo:27018/bookmeon?authSource=admin
    env_file:
      - .env
    ports:
      - '1337:1337'
    depends_on:
      - mongo

2. mongo.Dockerfile

###################
# MONGO container - for replication
###################

FROM mongo:4 As mongo

# we take over the default & start mongo in replica set mode in a background task
ENTRYPOINT mongod --port $MONGO_REPLICA_PORT --replSet rs0 --bind_ip 0.0.0.0 & MONGOD_PID=$!; \
# we prepare the replica set with a single node and prepare the root user config
INIT_REPL_CMD="rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: '$MONGO_REPLICA_HOST:$MONGO_REPLICA_PORT' }] })"; \
INIT_USER_CMD="db.getUser('$MONGO_INITDB_ROOT_USERNAME') || db.createUser({ user: '$MONGO_INITDB_ROOT_USERNAME', pwd: '$MONGO_INITDB_ROOT_PASSWORD', roles: [ 'root' ] })"; \
# we wait for the replica set to be ready and then submit the commands just above
until (mongo admin --port $MONGO_REPLICA_PORT --eval "$INIT_REPL_CMD && $INIT_USER_CMD"); do sleep 1; done; \
# we are done but we keep the container by waiting on signals from the mongo task
echo "REPLICA SET ONLINE"; wait $MONGOD_PID;

3. app.Dockerfile

###################
# base
###################

FROM node:20.5.1-alpine3.18 As base
RUN apk add openssl1.1-compat
RUN apk add musl

RUN npm i -g pnpm

###################
# deps install
###################

FROM base As deps

WORKDIR /my

COPY --chown=node:node ./package.json .

RUN pnpm i

###################
# build
###################

FROM base As build

WORKDIR /my

COPY --chown=node:node --from=deps ./my/. .
COPY --chown=node:node ./tsconfig* .
COPY --chown=node:node ./webpack.js .

COPY --chown=node:node ./prisma ./prisma
COPY --chown=node:node ./src ./src
COPY --chown=node:node ./aps ./aps

ARG DATABASE_URL="mongodb://root:prisma@mongo:27018/bookmeon?authSource=admin"

RUN pnpm exec prisma generate
RUN pnpm run build

USER node

CMD [ "node", "dist/main.js" ]

4. .env

DATABASE_URL="mongodb://root:prisma@mongo:27018/bookmeon?authSource=admin"

MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=prisma
MONGO_REPLICA_HOST=127.0.0.1
MONGO_REPLICA_PORT=27018

NODE_ENV=staging
FORCE_WWW=0
FORCE_TLS=0

报错信息

book_me_on-web-1  | PrismaClientInitializationError: Raw query failed. Code: `unknown`. Message: `Server selection timeout: No available servers. Topology: { Type: ReplicaSetNoPrimary, Servers: [ { Address: 127.0.0.1:27018, Type: Unknown, Error: Connection refused (os error 111) }, ] }`
book_me_on-web-1  |     at r (/my/node_modules/.pnpm/@prisma+client@5.0.0_prisma@5.0.0/node_modules/@prisma/client/runtime/library.js:103:2766)
book_me_on-web-1  |     at async Proxy.onModuleInit (/my/dist/prisma.service.js:14:9)
book_me_on-web-1  |     at async Promise.all (index 0)
book_me_on-web-1  |     at async callModuleInitHook (/my/node_modules/.pnpm/@nestjs+core@10.0.0_@nestjs+common@10.0.0_@nestjs+platform-express@10.0.0_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/hooks/on-module-init.hook.js:43:5)
book_me_on-web-1  |     at async NestApplication.callInitHook (/my/node_modules/.pnpm/@nestjs+core@10.0.0_@nestjs+common@10.0.0_@nestjs+platform-express@10.0.0_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/nest-application-context.js:223:13)
book_me_on-web-1  |     at async NestApplication.init (/my/node_modules/.pnpm/@nestjs+core@10.0.0_@nestjs+common@10.0.0_@nestjs+platform-express@10.0.0_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/nest-application.js:97:9)
book_me_on-web-1  |     at async NestApplication.listen (/my/node_modules/.pnpm/@nestjs+core@10.0.0_@nestjs+common@10.0.0_@nestjs+platform-express@10.0.0_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/nest-application.js:166:33)
book_me_on-web-1  |     at async bootstrap (/my/dist/main.js:21:5) {
book_me_on-web-1  |   clientVersion: '5.0.0',
book_me_on-web-1  |   errorCode: 'P2010'
book_me_on-web-1  | }
book_me_on-web-1  | 
book_me_on-web-1  | Node.js v20.5.1

排查更新

创建测试容器查看运行时环境变量,手动修改MONGO_REPLICA_HOST为172.19.0.2后,发现NestJS尝试连接172.19.0.2:27018,但通过mongo主机名ping到的MongoDB实际地址是172.19.0.3:27018,说明MongoDB实际运行IP与配置的固定IP不一致,导致连接失败。

解决方案

问题根源

MongoDB副本集初始化时,会将节点的地址返回给客户端,客户端后续会直接使用该地址建立连接。如果初始化时用的是127.0.0.1,NestJS容器内部访问127.0.0.1指向自身容器而非MongoDB容器;如果用固定IP,容器重启后IP可能变化,同样导致连接失败。Docker Compose内部容器可通过服务名(mongo)解析到正确地址,且该地址不会随容器重启变化。

修改步骤

  1. 更新docker-compose.yml中MongoDB的环境变量
    将MONGO_REPLICA_HOST改为服务名mongo:
services:
  mongo:
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: prisma
      MONGO_REPLICA_HOST: mongo  # 替换原127.0.0.1
      MONGO_REPLICA_PORT: 27018
  1. 更新.env文件中的MONGO_REPLICA_HOST
MONGO_REPLICA_HOST=mongo
  1. 保持mongo.Dockerfile不变
    该文件中已使用$MONGO_REPLICA_HOST变量,修改环境变量后会自动使用服务名初始化副本集。

  2. 可选:添加MongoDB健康检查
    确保NestJS启动时MongoDB副本集已就绪,在docker-compose.yml的mongo服务中添加健康检查:

services:
  mongo:
    # 其他配置...
    healthcheck:
      test: echo "rs.status().ok" | mongo admin --port $MONGO_REPLICA_PORT --quiet
      interval: 5s
      timeout: 5s
      retries: 5
  web:
    # 其他配置...
    depends_on:
      mongo:
        condition: service_healthy

验证

重新构建并启动容器:

docker-compose down -v
docker-compose up --build

此时NestJS容器将通过服务名mongo连接MongoDB,且副本集返回的节点地址也是mongo:27018,容器内部可正常解析访问。

内容的提问来源于stack exchange,提问作者Rantiev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:17:02