MongoDB Docker副本集 - 应用程序连接超时

时间:2018-01-08 21:06:27

标签: mongodb docker

我成功地能够使用三个容器创建docker副本集:

CONTAINER ID        IMAGE               PORTS              NAMES
b530275d1958        mongo       0.0.0.0:30003->27017/tcp   mongo3
dca4fa2d6f93        mongo       0.0.0.0:30002->27017/tcp   mongo2
0b4823661cf1        mongo       0.0.0.0:27017->27017/tcp   mongo1

此外,已成功配置副本集:

rs0:PRIMARY> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2018-01-08T20:57:30.395Z"),
    "myState" : 1,
    "term" : NumberLong(16),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1515445046, 1),
            "t" : NumberLong(16)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1515445046, 1),
            "t" : NumberLong(16)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1515445046, 1),
            "t" : NumberLong(16)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1515445046, 1),
            "t" : NumberLong(16)
        }
    },
    "members" : [
        {
            "_id" : 0,
            "name" : "mongo1:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 898,
            "optime" : {
                "ts" : Timestamp(1515445046, 1),
                "t" : NumberLong(16)
            },
            "optimeDate" : ISODate("2018-01-08T20:57:26Z"),
            "electionTime" : Timestamp(1515444174, 1),
            "electionDate" : ISODate("2018-01-08T20:42:54Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "mongo2:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 877,
            "optime" : {
                "ts" : Timestamp(1515445046, 1),
                "t" : NumberLong(16)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1515445046, 1),
                "t" : NumberLong(16)
            },
            "optimeDate" : ISODate("2018-01-08T20:57:26Z"),
            "optimeDurableDate" : ISODate("2018-01-08T20:57:26Z"),
            "lastHeartbeat" : ISODate("2018-01-08T20:57:29.056Z"),
            "lastHeartbeatRecv" : ISODate("2018-01-08T20:57:30.324Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "mongo1:27017",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "mongo3:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 871,
            "optime" : {
                "ts" : Timestamp(1515445046, 1),
                "t" : NumberLong(16)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1515445046, 1),
                "t" : NumberLong(16)
            },
            "optimeDate" : ISODate("2018-01-08T20:57:26Z"),
            "optimeDurableDate" : ISODate("2018-01-08T20:57:26Z"),
            "lastHeartbeat" : ISODate("2018-01-08T20:57:29.055Z"),
            "lastHeartbeatRecv" : ISODate("2018-01-08T20:57:29.506Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "mongo1:27017",
            "configVersion" : 1
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1515445046, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1515445046, 1),
        "signature" : {
            "hash" : BinData(0,"c3aBSVWElstPhnBx3c5NysBfdmk="),
            "keyId" : NumberLong("6504664228182360065")
        }
    }
}

请务必注意,它只是端口270173000230003

上的一个仅限VM的连接

然而,当我的PHP应用程序使用我附加到它的mongo DSN字符串连接到它时,我似乎遇到了问题

mongodb://<username>:<pass>@172.31.6.177:27017,172.31.6.177:30002,172.31.6.177:30003/opsserver-main?replicaSet=rs0&amp;authSource=admin"
我的PHP应用程序

错误

[Doctrine\MongoDB\Exception\ResultException]                                                  
  No suitable servers found: `serverSelectionTimeoutMS` expired: [connection timeout calling i  
  smaster on '172.31.6.177:27017'] [connection timeout calling ismaster on 'mongo1:27017'] [co  
  nnection timeout calling ismaster on 'mongo2:27017'] [connection timeout calling ismaster on  
   'mongo3:27017']  

我很奇怪它知道容器名称,或者至少尝试连接它。我做错了什么?

1 个答案:

答案 0 :(得分:2)

这是因为在docker网络中,容器mongo1mongo2mongo3可以找到彼此。但是,主机系统不知道这些名称,因此您的应用程序无法连接到整个集合。

您可以尝试从主机系统ping mongo1,并在其中说Unknown host

解决此问题的最简单方法是更改​​副本集配置中的主机名(使用rs.initiate(...)启动副本集时使用的主机名),例如:

  • mongo1:27017 - &gt; <your local hostname>:27017
  • mongo2:27017 - &gt; <your local hostname>:30002
  • mongo3:27017 - &gt; <your local hostname>:30003

<your local hostname>替换为hostname -f命令的输出。

这样,您的本地主机可以找到所有副本集节点,并且所有副本集节点仍然可以通过本地主机的端口映射找到彼此。