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

使用Docker Compose部署Express+MongoDB时数据库连接失败

问题:Docker部署Express+MongoDB API无法连接数据库

我尝试用Docker容器部署一个基于Express和MongoDB的小型API,但无法连接到数据库。以下是相关代码及报错信息:

连接脚本

const mongoose = require('mongoose');
const result = require('dotenv').config();
const logger = require('../logger/api.logger');
const { DB_USER, DB_PASS, DB_HOST, DB_PORT, DB_NAME } = process.env

const connect = () => {

    const url = `mongodb://@${DB_HOST}:${DB_PORT}/${DB_NAME}`;
    logger.info("CONNECTION_STRING = " + url);
    
    mongoose.connect(url, {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        dbName: process.env.DB_NAME,
    })

    mongoose.connection.once("open", async () => {
        logger.info("Connected to database");
    });
      
    mongoose.connection.on("error", (err) => {
        logger.error("Error connecting to database  ", err);
    });
}

const disconnect = () => {
    
    if (!mongoose.connection) {
      return;
    }
    
    mongoose.disconnect();

    mongoose.once("close", async () => {
        console.log("Diconnected  to database");
    });
};

module.exports = {
    connect,
    disconnect
}

.env文件

APP_PORT=3333
DB_NAME=first_db
DB_PORT=2717
DB_HOST=db_container

app.js文件

const express = require('express');

const cors = require("cors");

const app = express();

app.use(cors());
app.use(express.json());

// Routes
const router = require('./routes/router');
app.use(router);

// DB Connection
const database = require('./database/connection');
database.connect();

module.exports = app;

docker-compose.yml文件

version: '3.9'

services:
# Mongo DB
  mongo_db:
    image: mongo:latest
    container_name: db_container
    restart: always
    ports:
      - '${DB_PORT}:2717'
    volumes:
      - mongo_db:/data/db
    environment:
      MONGO_INITDB_DATABASE: ${DB_NAME}
      MONGO_INITDB_ROOT_USERNAME: ${DB_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${DB_PASS}
# Node API Service      
  api:
    build: .
    ports:
      - '${APP_PORT}:${APP_PORT}'
    depends_on:
      - mongo_db
    volumes:
      - .:/usr/src/
    env_file:
      - .env
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "5"

volumes:
  mongo_db: {}

报错信息

db_container  | {"t":{"$date":"2023-03-17T20:36:51.205+00:00"},"s":"I",  "c":"NETWORK",  "id":23015,   "ctx":"listener","msg":"Listening on","attr":{"address":"0.0.0.0"}}
db_container  | {"t":{"$date":"2023-03-17T20:36:51.205+00:00"},"s":"I",  "c":"NETWORK",  "id":23016,   "ctx":"listener","msg":"Waiting for connections","attr":{"port":27017,"ssl":"off"}}
docker-api-1  | MongooseServerSelectionError: connect ECONNREFUSED 172.23.0.2:2717
docker-api-1  |     at _handleConnectionErrors (/app/node_modules/mongoose/lib/connection.js:755:11)
docker-api-1  |     at NativeConnection.openUri (/app/node_modules/mongoose/lib/connection.js:730:11)
docker-api-1  |     at runNextTicks (node:internal/process/task_queues:60:5)
docker-api-1  |     at listOnTimeout (node:internal/timers:537:9)
docker-api-1  |     at process.processTimers (node:internal/timers:511:7)
docker-api-1  |     at async Object.connect (/app/src/database/connection.js:82:7) {
docker-api-1  |   reason: TopologyDescription {
docker-api-1  |     type: 'Unknown',
docker-api-1  |     servers: Map(1) { 'db_container:2717' => [ServerDescription] },
docker-api-1  |     stale: false,
docker-api-1  |     compatible: true,
docker-api-1  |     heartbeatFrequencyMS: 10000,
docker-api-1  |     localThresholdMS: 15,
docker-api-1  |     setName: null,
docker-api-1  |     maxElectionId: null,
docker-api-1  |     maxSetVersion: null,
docker-api-1  |     commonWireVersion: 0,
docker-api-1  |     logicalSessionTimeoutMinutes: null
docker-api-1  |   },
docker-api-1  |   code: undefined
docker-api-1  | }
docker-api-1 exited with code 1

解决方案

1. 修正端口不匹配问题

从报错和Mongo日志能看到:

  • Mongo容器内部监听的是默认端口27017
  • API容器却尝试连接2717端口

Docker容器间通信用容器内部端口,不是宿主机映射的端口。修改如下:

  • 更新.env文件,将DB_PORT改为Mongo容器内部默认端口:
DB_PORT=27017
  • 调整docker-compose.yml中Mongo的端口映射,把宿主机端口和容器端口区分开(比如宿主机用2717访问,容器内部还是27017):
ports:
  - '2717:27017'

2. 补充MongoDB认证信息

  • .env文件添加缺失的数据库用户名和密码:
DB_USER=root
DB_PASS=your_secure_password
  • 修正连接脚本中的MongoDB连接字符串,补充认证信息并指定认证源(root用户默认在admin库下认证):
const url = `mongodb://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}?authSource=admin`;

3. 确保数据库就绪后再启动API

depends_on仅保证启动顺序,不会等待数据库完全就绪。给Mongo服务添加健康检查,让API等数据库就绪后再启动:

  • 更新docker-compose.yml的mongo_db服务:
mongo_db:
  image: mongo:latest
  container_name: db_container
  restart: always
  ports:
    - '2717:27017'
  volumes:
    - mongo_db:/data/db
  environment:
    MONGO_INITDB_DATABASE: ${DB_NAME}
    MONGO_INITDB_ROOT_USERNAME: ${DB_USER}
    MONGO_INITDB_ROOT_PASSWORD: ${DB_PASS}
  healthcheck:
    test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
    interval: 10s
    timeout: 5s
    retries: 5
  • 更新api服务的depends_on配置:
depends_on:
  mongo_db:
    condition: service_healthy

4. 可选:添加连接重试逻辑

在连接脚本中添加重试机制,避免因数据库启动慢导致的连接失败:

const connect = async () => {
  const url = `mongodb://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}?authSource=admin`;
  logger.info("CONNECTION_STRING = " + url);

  const connectWithRetry = () => {
    mongoose.connect(url, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    })
    .then(() => logger.info("Connected to database"))
    .catch(err => {
      logger.error("Connection failed, retrying in 5s...", err);
      setTimeout(connectWithRetry, 5000);
    });
  };

  connectWithRetry();
};

内容的提问来源于stack exchange,提问作者Vinícius Albino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:40:01