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

Docker容器中Node.js API连接MongoDB失败求助

问题解决步骤

1. 修复Dockerfile的核心错误

你的Dockerfile存在两个关键问题:

  • COPY指令错误地将代码复制到容器内的宿主机路径(/Users/styles/Programming/DroneAPI2),容器是独立的Alpine系统,不存在该路径;之前创建的/home/droneAPI目录也未被使用。
  • ENV变量定义有多余空格,MONGO_DB_USERNAME = admin的空格会导致变量值包含无效空格,需去掉等号两侧空格。

修改后的Dockerfile:

FROM node:19-alpine

# 正确定义环境变量,去掉等号两侧空格
ENV MONGO_DB_USERNAME=admin \
    MONGO_DB_PWD=password

# 设置容器内的工作目录
WORKDIR /home/droneAPI

# 将宿主机当前目录的所有文件复制到容器工作目录
COPY . .

# 安装项目依赖(如果你的项目有package.json,必须添加这一步)
RUN npm install

# 使用容器内的相对路径启动服务
CMD ["node", "./Drones/server.js"]

重新构建镜像:

docker build -t droneapi:1.0 .

2. 将API服务加入Docker Compose网络

单独启动的容器默认不在同一个Docker网络,无法通过服务名(如mongodb)通信。最直接的方式是把API服务加入到你的MongoDB Compose配置中,让所有服务共享同一个网络。

修改后的mongo.yaml:

version: '3'
services:
    mongodb:
        image: mongo
        ports:
            - 27017:27017
        environment:
            - MONGO_INITDB_ROOT_USERNAME=admin
            - MONGO_INITDB_ROOT_PASSWORD=password
        # 持久化MongoDB数据,避免容器删除后数据丢失
        volumes:
            - mongodb_data:/data/db
    mongo-express:
        image: mongo-express
        ports:
            - 8081:8081
        environment:
            - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
            - ME_CONFIG_MONGODB_ADMINPASSWORD=password
            - ME_CONFIG_MONGODB_SERVER=mongodb
        # 确保MongoDB启动后再启动mongo-express
        depends_on:
            - mongodb
    droneapi:
        # 使用你本地构建的API镜像
        image: droneapi:1.0
        ports:
            # 假设你的API使用3000端口,映射到宿主机3000端口
            - 3000:3000
        environment:
            # 通过环境变量传递数据库配置,避免硬编码
            - MONGO_DB_USERNAME=admin
            - MONGO_DB_PWD=password
            - MONGO_DB_HOST=mongodb
            - MONGO_DB_PORT=27017
            - MONGO_DB_NAME=drobedb
        # 依赖MongoDB服务,确保其先启动
        depends_on:
            - mongodb
# 定义数据卷,持久化MongoDB数据
volumes:
    mongodb_data:

3. 修改Mongoose连接逻辑,使用环境变量

硬编码连接字符串既不灵活也不符合Docker最佳实践,改用环境变量读取配置:

const connectDB = async () => {
    try{
        // 从环境变量中获取数据库配置
        const username = process.env.MONGO_DB_USERNAME;
        const password = process.env.MONGO_DB_PWD;
        const host = process.env.MONGO_DB_HOST || 'localhost';
        const port = process.env.MONGO_DB_PORT || 27017;
        const dbName = process.env.MONGO_DB_NAME || 'drobedb';

        // 动态拼接连接字符串
        const connStr = `mongodb://${username}:${password}@${host}:${port}/${dbName}`;
        
        const conn = await mongoose.connect(connStr);
        console.log(`MongoDB Connected: ${conn.connection.host}`.cyan.underline);

    }catch (error){
       console.log(`Error: ${error.message}`.red.underline.bold);
       process.exit(1);
    }
}

4. 启动所有服务

通过Docker Compose一次性启动所有服务,它们会自动加入同一个网络,互相之间可以通过服务名通信:

docker-compose -f mongo.yaml up -d

补充说明

  • 直接用docker run droneapi:1.0启动容器时,它与MongoDB容器不在同一网络,因此无法解析mongodb主机名,导致getaddrinfo ENOTFOUND mongodb错误。
  • 换成localhost后,容器内的localhost指向容器自身而非宿主机,而容器内没有运行MongoDB,因此出现connect ECONNREFUSED 127.0.0.1:27017错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:20:23