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
相关产品推荐
相关产品推荐

