使用Docker Compose无法运行Mongo Express

9
这是我在使用Node.js和Docker方面的第一篇文章,请谅解我的问题。我正在使用docker-compose运行Mongo和Mongo Express容器,但是Mongo Express无法正常运行。当我不使用docker-compose直接运行Mongo和Mongo Express时,它可以完美地工作。因此,我认为我可能遇到了docker-compose或者Node.js代码的一些问题。 docker-compose.yaml
version: '3'
services:
  mongodb:
    image: mongo
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
  mongo-express:
    image: mongo-express
    ports:
      - 8080:8081
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
      - ME_CONFIG_MONGODB_ADMINPASSWORD=password
      - ME_CONFIG_MONGODB_SERVER=mongodb

server.js

let express = require('express');
let path = require('path');
let fs = require('fs');
let MongoClient = require('mongodb').MongoClient;
let bodyParser = require('body-parser');
let app = express();

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, "index.html"));
  });

app.get('/profile-picture', function (req, res) {
  let img = fs.readFileSync(path.join(__dirname, "images/profile-1.jpg"));
  res.writeHead(200, {'Content-Type': 'image/jpg' });
  res.end(img, 'binary');
});

// use when starting application locally
let mongoUrlLocal = "mongodb://admin:password@localhost:27017";

// use when starting application as docker container
let mongoUrlDocker = "mongodb://admin:password@mongodb";

// pass these options to mongo client connect request to avoid DeprecationWarning for current Server Discovery and Monitoring engine
let mongoClientOptions = { useNewUrlParser: true, useUnifiedTopology: true };

// "user-account" in demo with docker. "my-db" in demo with docker-compose
let databaseName = "my-db";

app.post('/update-profile', function (req, res) {
  let userObj = req.body;

  MongoClient.connect(mongoUrlLocal, mongoClientOptions, function (err, client) {
    if (err) throw err;

    let db = client.db(databaseName);
    userObj['userid'] = 1;

    let myquery = { userid: 1 };
    let newvalues = { $set: userObj };

    db.collection("users").updateOne(myquery, newvalues, {upsert: true}, function(err, res) {
      if (err) throw err;
      client.close();
    });

  });
  // Send response
  res.send(userObj);
});

app.get('/get-profile', function (req, res) {
  let response = {};
  // Connect to the db
  MongoClient.connect(mongoUrlLocal, mongoClientOptions, function (err, client) {
    if (err) throw err;

    let db = client.db(databaseName);

    let myquery = { userid: 1 };

    db.collection("users").findOne(myquery, function (err, result) {
      if (err) throw err;
      response = result;
      client.close();

      // Send response
      res.send(response ? response : {});
    });
  });
});

app.listen(3000, function () {
  console.log("app listening on port 3000!");
});

如果我运行docker ps,我只能看到Mongo正在运行。
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                           NAMES
d20c4784d316   mongo     "docker-entrypoint.s…"   43 seconds ago   Up 38 seconds   0.0.0.0:27017->27017/tcp, :::27017->27017/tcp   nodeapplications_mongodb_1

当我运行以下命令来启动我的docker-compose时,出现了下面这个日志,我怀疑存在问题。感谢任何帮助。

docker-compose -f docker-compose.yaml up

日志

mongo-express_1  | Welcome to mongo-express
mongo-express_1  | ------------------------
mongo-express_1  | 
mongo-express_1  | 
mongo-express_1  | (node:7) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
mongo-express_1  | Could not connect to database using connectionString: mongodb://admin:password@mongodb:27017/"
mongo-express_1  | (node:7) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [mongodb:27017] on first connect [Error: connect ECONNREFUSED 172.19.0.3:27017
mongo-express_1  |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) {
mongo-express_1  |   name: 'MongoNetworkError'
mongo-express_1  | }]
mongo-express_1  |     at Pool.<anonymous> (/node_modules/mongodb/lib/core/topologies/server.js:438:11)
mongo-express_1  |     at Pool.emit (events.js:314:20)
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/pool.js:562:14
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/pool.js:995:11
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/connect.js:32:7
mongo-express_1  |     at callback (/node_modules/mongodb/lib/core/connection/connect.js:280:5)
mongo-express_1  |     at Socket.<anonymous> (/node_modules/mongodb/lib/core/connection/connect.js:310:7)
mongo-express_1  |     at Object.onceWrapper (events.js:421:26)
mongo-express_1  |     at Socket.emit (events.js:314:20)
mongo-express_1  |     at emitErrorNT (internal/streams/destroy.js:92:8)
mongo-express_1  |     at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
mongo-express_1  |     at processTicksAndRejections (internal/process/task_queues.js:84:21)
mongo-express_1  | (node:7) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

根据 @Blunderchips 的建议,更新 1

server.js

let express = require('express');
let path = require('path');
let fs = require('fs');
let MongoClient = require('mongodb').MongoClient;
let bodyParser = require('body-parser');
let app = express();

const dbServer = process.env.ME_CONFIG_MONGODB_SERVER;
const dbPassword = process.env.ME_CONFIG_MONGODB_ADMINPASSWORD;
const dbUserName = process.env.ME_CONFIG_MONGODB_ADMINUSERNAME;
const dbPort = process.env.ME_CONFIG_MONGODB_PORT;

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, "index.html"));
  });

app.get('/profile-picture', function (req, res) {
  let img = fs.readFileSync(path.join(__dirname, "images/profile-1.jpg"));
  res.writeHead(200, {'Content-Type': 'image/jpg' });
  res.end(img, 'binary');
});

// use when starting application locally
//let mongoUrlLocal = "mongodb://admin:password@localhost:27017";

// use when starting application as docker container
let mongoUrlDocker = `mongodb://${dbUserName}:${dbPassword}@${dbServer}:${dbPort}`;//"mongodb://admin:password@mongodb:27017";//"mongodb://admin:password@mongodb";

// pass these options to mongo client connect request to avoid DeprecationWarning for current Server Discovery and Monitoring engine
let mongoClientOptions = { useNewUrlParser: true, useUnifiedTopology: true };

// "user-account" in demo with docker. "my-db" in demo with docker-compose
let databaseName = "my-db";

app.post('/update-profile', function (req, res) {
  let userObj = req.body;

  MongoClient.connect(mongoUrlDocker, mongoClientOptions, function (err, client) {
    if (err) throw err;

    let db = client.db(databaseName);
    userObj['userid'] = 1;

    let myquery = { userid: 1 };
    let newvalues = { $set: userObj };

    db.collection("users").updateOne(myquery, newvalues, {upsert: true}, function(err, res) {
      if (err) throw err;
      client.close();
    });

  });
  // Send response
  res.send(userObj);
});

app.get('/get-profile', function (req, res) {
  let response = {};
  // Connect to the db
  MongoClient.connect(mongoUrlDocker, mongoClientOptions, function (err, client) {
    if (err) throw err;

    let db = client.db(databaseName);

    let myquery = { userid: 1 };

    db.collection("users").findOne(myquery, function (err, result) {
      if (err) throw err;
      response = result;
      client.close();

      // Send response
      res.send(response ? response : {});
    });
  });
});

app.listen(3000, function () {
  console.log("app listening on port 3000!");
});

docker-compose.yaml

version: '3'
services:
  mongodb:
    image: mongo
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
  mongo-express:
    image: mongo-express
    ports:
      - 8080:8081
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
      - ME_CONFIG_MONGODB_ADMINPASSWORD=password
      - ME_CONFIG_MONGODB_SERVER=mongodb
    links: 
        - mongodb:mongodb

我仍然看不到Mongo Express正在运行。
docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS                                           NAMES
23428dc0c3a1   mongo     "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:27017->27017/tcp, :::27017->27017/tcp   nodeapplications_mongodb_1

日志

mongo-express_1  | Welcome to mongo-express
mongo-express_1  | ------------------------
mongo-express_1  | 
mongo-express_1  | 
mongo-express_1  | (node:7) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
mongo-express_1  | Could not connect to database using connectionString: mongodb://admin:password@mongodb:27017/"
mongo-express_1  | (node:7) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [mongodb:27017] on first connect [Error: connect ECONNREFUSED 172.23.0.2:27017
mongo-express_1  |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) {
mongo-express_1  |   name: 'MongoNetworkError'
mongo-express_1  | }]
mongo-express_1  |     at Pool.<anonymous> (/node_modules/mongodb/lib/core/topologies/server.js:438:11)
mongo-express_1  |     at Pool.emit (events.js:314:20)
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/pool.js:562:14
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/pool.js:995:11
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/connect.js:32:7
mongo-express_1  |     at callback (/node_modules/mongodb/lib/core/connection/connect.js:280:5)
mongo-express_1  |     at Socket.<anonymous> (/node_modules/mongodb/lib/core/connection/connect.js:310:7)
mongo-express_1  |     at Object.onceWrapper (events.js:421:26)
mongo-express_1  |     at Socket.emit (events.js:314:20)
mongo-express_1  |     at emitErrorNT (internal/streams/destroy.js:92:8)
mongo-express_1  |     at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
mongo-express_1  |     at processTicksAndRejections (internal/process/task_queues.js:84:21)
mongo-express_1  | (node:7) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
mongo-express_1  | (node:7) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

更新2

let express = require('express');
let path = require('path');
let fs = require('fs');
let MongoClient = require('mongodb').MongoClient;
let bodyParser = require('body-parser');
let app = express();

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, "index.html"));
  });

app.get('/profile-picture', function (req, res) {
  let img = fs.readFileSync(path.join(__dirname, "images/profile-1.jpg"));
  res.writeHead(200, {'Content-Type': 'image/jpg' });
  res.end(img, 'binary');
});

// use when starting application locally
//let mongoUrlLocal = "mongodb://admin:password@localhost:27017";

// use when starting application as docker container
let mongoUrlDocker = "mongodb://admin:password@mongodb:27017";

// pass these options to mongo client connect request to avoid DeprecationWarning for current Server Discovery and Monitoring engine
let mongoClientOptions = { useNewUrlParser: true, useUnifiedTopology: true };

// "user-account" in demo with docker. "my-db" in demo with docker-compose
let databaseName = "my-db";

app.post('/update-profile', function (req, res) {
  let userObj = req.body;

  MongoClient.connect(mongoUrlDocker, mongoClientOptions, function (err, client) {
    if (err) throw err;

    let db = client.db(databaseName);
    userObj['userid'] = 1;

    let myquery = { userid: 1 };
    let newvalues = { $set: userObj };

    db.collection("users").updateOne(myquery, newvalues, {upsert: true}, function(err, res) {
      if (err) throw err;
      client.close();
    });

  });
  // Send response
  res.send(userObj);
});

app.get('/get-profile', function (req, res) {
  let response = {};
  // Connect to the db
  MongoClient.connect(mongoUrlDocker, mongoClientOptions, function (err, client) {
    if (err) throw err;

    let db = client.db(databaseName);

    let myquery = { userid: 1 };

    db.collection("users").findOne(myquery, function (err, result) {
      if (err) throw err;
      response = result;
      client.close();

      // Send response
      res.send(response ? response : {});
    });
  });
});

app.listen(3000, function () {
  console.log("app listening on port 3000!");
});

更新 3

docker-compose

version: '3'
services:
  mongodb:
    image: mongo
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
  mongo-express:
    image: mongo-express
    ports:
      - 8080:8081
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
      - ME_CONFIG_MONGODB_ADMINPASSWORD=password
      - ME_CONFIG_MONGODB_SERVER=mongodb
    links: 
        - mongodb:mongodb
    restart: on-failure

完整日志

 mongo-express_1  | Welcome to mongo-express
mongo-express_1  | ------------------------
mongo-express_1  | 
mongo-express_1  | 
mongodb_1        | {"t":{"$date":"2021-07-04T10:41:58.806+00:00"},"s":"I",  "c":"STORAGE",  "id":22318,   "ctx":"SignalHandler","msg":"Shutting down session sweeper thread"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:41:58.806+00:00"},"s":"I",  "c":"STORAGE",  "id":22319,   "ctx":"SignalHandler","msg":"Finished shutting down session sweeper thread"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:41:58.807+00:00"},"s":"I",  "c":"STORAGE",  "id":22322,   "ctx":"SignalHandler","msg":"Shutting down checkpoint thread"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:41:58.807+00:00"},"s":"I",  "c":"STORAGE",  "id":22323,   "ctx":"SignalHandler","msg":"Finished shutting down checkpoint thread"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:41:58.807+00:00"},"s":"I",  "c":"STORAGE",  "id":4795902, "ctx":"SignalHandler","msg":"Closing WiredTiger","attr":{"closeConfig":"leak_memory=true,"}}
mongodb_1        | {"t":{"$date":"2021-07-04T10:41:58.810+00:00"},"s":"I",  "c":"STORAGE",  "id":22430,   "ctx":"SignalHandler","msg":"WiredTiger message","attr":{"message":"[1625395318:810568][28:0x7f50eec9b700], close_ckpt: [WT_VERB_CHECKPOINT_PROGRESS] saving checkpoint snapshot min: 48, snapshot max: 48 snapshot count: 0, oldest timestamp: (0, 0) , meta checkpoint timestamp: (0, 0)"}}
mongo-express_1  | (node:7) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
mongo-express_1  | Could not connect to database using connectionString: mongodb://admin:password@mongodb:27017/"
mongo-express_1  | (node:7) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [mongodb:27017] on first connect [Error: connect ECONNREFUSED 172.27.0.2:27017
mongo-express_1  |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) {
mongo-express_1  |   name: 'MongoNetworkError'
mongo-express_1  | }]
mongo-express_1  |     at Pool.<anonymous> (/node_modules/mongodb/lib/core/topologies/server.js:438:11)
mongo-express_1  |     at Pool.emit (events.js:314:20)
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/pool.js:562:14
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/pool.js:995:11
mongo-express_1  |     at /node_modules/mongodb/lib/core/connection/connect.js:32:7
mongo-express_1  |     at callback (/node_modules/mongodb/lib/core/connection/connect.js:280:5)
mongo-express_1  |     at Socket.<anonymous> (/node_modules/mongodb/lib/core/connection/connect.js:310:7)
mongo-express_1  |     at Object.onceWrapper (events.js:421:26)
mongo-express_1  |     at Socket.emit (events.js:314:20)
mongo-express_1  |     at emitErrorNT (internal/streams/destroy.js:92:8)
mongo-express_1  |     at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
mongo-express_1  |     at processTicksAndRejections (internal/process/task_queues.js:84:21)
mongo-express_1  | (node:7) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
mongo-express_1  | (node:7) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
mongodb_1        | {"t":{"$date":"2021-07-04T10:42:00.871+00:00"},"s":"I",  "c":"STORAGE",  "id":4795901, "ctx":"SignalHandler","msg":"WiredTiger closed","attr":{"durationMillis":2064}}
mongodb_1        | {"t":{"$date":"2021-07-04T10:42:00.871+00:00"},"s":"I",  "c":"STORAGE",  "id":22279,   "ctx":"SignalHandler","msg":"shutdown: removing fs lock..."}
mongodb_1        | {"t":{"$date":"2021-07-04T10:42:00.872+00:00"},"s":"I",  "c":"-",        "id":4784931, "ctx":"SignalHandler","msg":"Dropping the scope cache for shutdown"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:42:00.873+00:00"},"s":"I",  "c":"FTDC",     "id":4784926, "ctx":"SignalHandler","msg":"Shutting down full-time data capture"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:42:00.873+00:00"},"s":"I",  "c":"FTDC",     "id":20626,   "ctx":"SignalHandler","msg":"Shutting down full-time diagnostic data capture"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:42:00.878+00:00"},"s":"I",  "c":"CONTROL",  "id":20565,   "ctx":"SignalHandler","msg":"Now exiting"}
mongodb_1        | {"t":{"$date":"2021-07-04T10:42:00.879+00:00"},"s":"I",  "c":"CONTROL",  "id":23138,   "ctx":"SignalHandler","msg":"Shutting down","attr":{"exitCode":0}}
nodeapplications_mongo-express_1 exited with code 0
mongodb_1        | 
mongodb_1        | MongoDB init process complete; ready for start up.

请再仔细阅读我的答案。只是在底部复制粘贴连接内容无法解决问题。如果你想使用那种方法,我们需要定义一个端口。 - Blunderchips
如果你运行 docker-compose up 并阅读整个日志,是否有 MongoDB 启动消息在 mongo-express 失败之后?设置 mongo-express: { restart: on-failure } 是否有帮助,或者使用 Docker Compose wait for container X before starting Y 中描述的更复杂的技术之一? - David Maze
@DavidMaze 我尝试在mongo express的docker-compose中添加restart: on-failure,但没有成功。让我更新我的docker-compose和完整日志。 - Aniket Tiwari
5
在与mongo-express故障后,MongoDB ready for start up是我要寻找的症状。如果mongo-express以代码0(成功)退出,即使它无法启动,则您可能需要更强的重启策略,例如restart: unless-stopped - David Maze
@DavidMaze 谢谢,现在它可以工作了。请把它发布为答案。 - Aniket Tiwari
最好使用 **depends_on: ["mongodb"]**,因为这是一个依赖问题。这里的问题显然是 mongo-express 在 mongo 还没有准备好的情况下启动了,所以它(mongo-express)无法连接,并一直处于失败状态。 - Rachid
4个回答

19

如@David Maze所建议的,通过添加restart: unless-stopped,它起作用了。

version: '3'
services:
  mongodb:
    image: mongo
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
  mongo-express:
    image: mongo-express
    ports:
      - 8081:8081
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
      - ME_CONFIG_MONGODB_ADMINPASSWORD=password
      - ME_CONFIG_MONGODB_SERVER=mongodb
    restart: unless-stopped

4
我正在学习techworkwithNana的同一门课程,也遇到了同样的问题。我不明白为什么讲师没有出现这个错误?添加restart: unless-stopped如何解决这个问题? - Jag99
因为这是一个旧版本,在它能够正常工作的时候。 - Muhammad Faizan

2

加上 restart: unless-stopped 是有效的,但这似乎不是根本原因。在阅读了这篇文章之后 - https://docs.docker.com/compose/startup-order/,我认为问题在于 mongo-express 依赖于 mongo 服务,所以理想情况下它应该在 mongo 运行之后启动,但似乎没有一个优雅的解决方案来解决这个问题,depends_on 选项可以减少问题,但不能完全解决。

检查 depends_on 选项的限制(或设计),https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on

引用

depends_on 在启动 web 之前并不会等待 db 和 redis “准备就绪”,只会等到它们已经启动。如果你需要等待一个服务准备就绪,请参阅“控制启动顺序”以获取更多关于此问题的信息和解决策略。

我的最终 yaml 文件:

version: '3'
services:
  mongodb:
    image: mongo
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
  mongo-express:
    image: mongo-express
    ports:
      - 8080:8081
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
      - ME_CONFIG_MONGODB_ADMINPASSWORD=password
      - ME_CONFIG_MONGODB_SERVER=mongodb
    depends_on:
      - "mongodb"
    restart: unless-stopped

2023-06-23的更新:
检测服务就绪状态的解决方案是使用condition属性,并选择以下选项之一:
查看:https://docs.docker.com/compose/startup-order/#control-startup

1

问题显然是mongo-express在mongo还没有准备好的情况下启动了,因此它(mongo-express)无法连接并一直处于失败状态。

  • 使用restart: unless-stopped是一个解决方案,但对于这个目的来说不够干净。

正确的方法是添加对mongo-express的依赖。它应该在mongo启动完成后开始运行,为了实现这一点,请使用:

depends_on:
      - mongodb

1
那不是一个解决方案。它并不等待MongoDB准备就绪:它只等待容器启动。 - Doradus

0
问题似乎在于您已配置了网络。 在 express 服务器中,它试图连接到在其自己的本地主机(容器的 127.0.0.1 而不是您的本地计算机)上运行的 Mongo 实例。由于在您的 express 服务中没有运行 MongoDB 实例,因此会抛出 ECONNREFUSED(错误连接被拒绝)。我们需要做的是将 DB 容器放在可从 express 服务访问的网络中并连接到它。您可以在这里找到有关使用 docker-compose 进行网络设置的 文档 的更多信息。
在这种情况下,我发现最简便的方法就是“链接”两个服务,如下所示:
version: '3'
services:
  mongodb:
    image: mongo
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password

  mongo-express:
    image: mongo-express
    ports:
      - 8080:8081
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
      - ME_CONFIG_MONGODB_ADMINPASSWORD=password
      - ME_CONFIG_MONGODB_SERVER=mongodb
    links: 
        - mongodb:mongodb

然后将mongoUrlLocal更改为mongodb://admin:password@mongodb:27017。请查看此处的文档以获取更多信息。实际上,这在mongo-express服务中创建了一个小伪DNS记录,指向运行数据库的容器,因此每当您尝试连接到“mongodb”地址时,您都会连接到运行数据库的容器。请注意,这仅适用于链接的服务,因此您无法从本地计算机连接到“mongodb”。
除了我建议您执行的操作之外,我还为您的数据库连接设置了环境变量。目前我看到您有ME_CONFIG_MONGODB_SERVER,但未使用mongoUrlLocalmongoUrlDocker。我认为最好从process.env中提取连接字符串信息,然后像您已经在docker-compose文件中一样传递环境变量。
例如,像这样:
const dbServer = process.env.ME_CONFIG_MONGODB_SERVER;
const dbPassword = process.env.ME_CONFIG_MONGODB_ADMINPASSWORD;
const dbUserName = process.env.ME_CONFIG_MONGODB_ADMINUSERNAME;
const dbPort = process.env.ME_CONFIG_MONGODB_PORT;

let mongoUrl = `mongodb://${dbUserName}:${dbPassword}@${dbServer}:${dbPort}`;

我尝试了你提供的解决方案并更新了我的问题,但对我没有起作用。 - Aniket Tiwari
你的 MongoDB URL 是什么? - Blunderchips
请注意底部的连接字符串只是一个示例,重要的是链接容器。 - Blunderchips
2
“links:”是第一代Docker网络中已经过时的设置;在现代Docker中它们是不必要的,因此Compose文件不需要更改(实际上,原始问题的错误消息显示客户端成功解析了“mongodb”主机名)。环境变量配置是一个好建议,但这里可能不是核心问题。 - David Maze
对我来说,两个链接都有效:mongodb:mongodb和restart: unless-stopped解决方案。使用链接选项mongo-express可以立即连接到mongodb。就像Aniket提到的那样,如果没有使用docker compose,mongodb和mongo-express容器都可以正常工作。只有在使用docker compose构建容器时,mongo-express才无法初始化。 - Jag99
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接