繁体   English   中英

第一次尝试时无法将节点连接到 docker 容器中的 mongoDB

[英]Cannot connect Node to mongoDB in docker container on first try

我正在尝试对接 Node.js 应用程序,该应用程序使用 mongoose 连接到 MongoDB。 当连接 URL 为: mongodb://localhost:27017/deposit时,只要我从 shell 运行node index.js ,它就会成功如果我重新启动计算机,然后尝试使用命令docker-compose up运行 dockerized 项目(在 url 中使用mongo而不是localhost ),则无法连接到 MongoDB。 但是在我再次尝试相同的命令后,它就成功了。

所以我的问题是为什么节点无法连接到 MongoDB 在计算机重新启动后第一次尝试?

PS。 Docker 在我尝试时正在运行

连接.js

const mongoose = require('mongoose');

const connection = "mongodb://mongo:27017/deposit";

const connectDb = () => {
    mongoose.connect(connection, {useNewUrlParser: true,  useUnifiedTopology: true}).then(res => console.log("Connected to DB"))
    .catch(err => console.log('>> Failed to connect to MongoDB, retrying...'));
};

module.exports = connectDb;

Dockerfile

 FROM node:latest

 RUN mkdir -p /app
 WORKDIR /app
 #/usr/src/app
 COPY package.json /app
 RUN npm install

 COPY . /app

 EXPOSE 7500

#  ENTRYPOINT ["node"]

 CMD ["node", "src/index.js"]

docker-compose.yml

version: "3"
services:
        deposit:
            container_name: deposit
            image: test/deposit
            restart: always
            build: .
            network_mode: host
            ports:
              - "7500:7500"
            depends_on:
              - mongo
        mongo:
              container_name: mongo
              image: mongo
              volumes:
                - /data:/data/db
              network_mode: host
              ports:
                - '27017:27017'

在您的情况下,节点应用程序在 mongo 准备好之前启动。 有两种方法可以解决这个问题: 在您的 docker-compose 或您的应用程序中处理它。 您可以使用wait-for-it.sh或编写wrapper script (两者都在此处描述)以确保您的节点应用程序在数据库准备好后启动。 正如 docker 文档所引用的那样,最好在您的应用程序中处理这个问题:

要处理这个问题,请将您的应用程序设计为在发生故障后尝试重新建立与数据库的连接。 如果应用程序重试连接,它最终可以连接到数据库。

最好的解决方案是在您的应用程序代码中执行此检查,无论是在启动时还是由于任何原因失去连接时

您可以按如下方式实施 mongo 重试(在答案中描述):

var connectWithRetry = function() {
  return mongoose.connect(mongoUrl, function(err) {
    if (err) {
      console.error('Failed to connect to mongo on startup - retrying in 5 sec', err);
      setTimeout(connectWithRetry, 5000);
    }
  });
};
connectWithRetry();

如评论中所述,数据库可能尚未准备好接受连接,因此一种方法是添加重试逻辑或另一种选择是

serverSelectionTimeoutMS -

使用 useUnifiedTopology,MongoDB 驱动程序将尝试找到一个服务器来发送任何给定的操作,并继续重试serverSelectionTimeoutMS毫秒。 如果未设置,MongoDB 驱动程序默认使用 30000(30 秒)。

所以试试下面的选项

const mongoose = require('mongoose');

const uri = 'mongodb://mongo:27017/deposit?retryWrites=true&w=majority';
mongoose.connect(uri, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  serverSelectionTimeoutMS: 50000
}).catch(err => console.log(err.reason));

但是,如果您初始化数据库脚本变得更大,则需要更多时间,因此如果这不起作用,则使用重试逻辑 go。 在上面的脚本中,它将等待 50 秒。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM