连接到远程 dockerized MongoDB 副本集
Connect to a remote dockerized MongoDB replica set
在我的远程机器上,我设置了一个 docker 容器机器,我使用 docker-compose 进行管理。
我为每个 MongoDB 实例创建了 3 docker 个容器,我想要在我的副本集中
mongodb_01:
image: mvertes/alpine-mongo
entrypoint: ['/usr/bin/mongod', '--bind_ip_all', '--replSet', 'rs0']
restart: always
ports:
- 10001:27017
volumes:
- ./mongodb/01:/data/db
mongodb_02:
image: mvertes/alpine-mongo
entrypoint: ['/usr/bin/mongod', '--bind_ip_all', '--replSet', 'rs0']
restart: always
depends_on:
- mongodb_01
ports:
- 10002:27017
volumes:
- ./mongodb/02:/data/db
mongodb_03:
image: mvertes/alpine-mongo
entrypoint: ['/usr/bin/mongod', '--bind_ip_all', '--replSet', 'rs0']
restart: always
depends_on:
- mongodb_02
ports:
- 10003:27017
volumes:
- ./mongodb/03:/data/db
我还配置了副本集。这是摘录:
"_id" : "rs0",
...
"members" : [
{
"_id" : 0,
"host" : "mongodb_01:27017",
...
},
{
"_id" : 1,
"host" : "mongodb_02:27017",
...
},
{
"_id" : 2,
"host" : "mongodb_03:27017",
...
}
],
...
}
一切正常,其他 docker 图像和此副本集之间的内部通信使用连接字符串正常工作
mongodb://mongodb_01:27017,mongodb_02:27017,mongodb_03:27017/<database>?replicaSet=rs0
问题是当我需要将远程客户端连接到这个副本集时。
例如,在我的开发机器上通过节点使用猫鼬,我得到:
MongoNetworkError: failed to connect to server [mongodb_02:27017] on first connect [MongoNetworkError: getaddrinfo ENOTFOUND mongodb_02 mongodb_02:27017]
有时会在 mongodb_03 上失败。
编辑:如前所述,这是我来自远程机器的连接字符串:
mongodb://<remote-host>:10001,<remote-host>:10002,<remote-host>:10003/<database>?replicaSet=rs0
编辑 2:使用像 Mongodb Compass 这样的客户端,我可以正确地成功连接到单个实例。当我添加副本集时,出现错误。
所以我尝试用mongodb(使用mongo:latest)创建一个虚拟容器。
$ docker run -it mongo:latest bash
和运行
mongo mongodb://<remote-host>:10001,<remote-host>:10002,<remote-host>:10003/<database>?replicaSet=rs0
我明白了
MongoDB shell version v4.0.6
connecting to: mongodb://<remote-host>:10001,<remote-host>:10002,<remote-host>:10003/<database>?gssapiServiceName=mongodb&replicaSet=rs0
2019-03-04T16:12:54.375+0000 I NETWORK [js] Starting new replica set monitor for rs0/<remote-host>:10001,<remote-host>:10002,<remote-host>:10003
2019-03-04T16:12:54.377+0000 I NETWORK [ReplicaSetMonitor-TaskExecutor] Successfully connected to <remote-host>:10003 (1 connections now open to <remote-host>:10003 with a 5 second timeout)
2019-03-04T16:12:54.377+0000 I NETWORK [js] Successfully connected to <remote-host>:10001 (1 connections now open to <remote-host>:10001 with a 5 second timeout)
2019-03-04T16:12:54.378+0000 I NETWORK [js] changing hosts to rs0/mongodb_01:27017,mongodb_02:27017,mongodb_03:27017 from rs0/<remote-host>:10001,<remote-host>:10002,<remote-host>:10003
2019-03-04T16:12:54.882+0000 W NETWORK [js] Unable to reach primary for set rs0
2019-03-04T16:12:54.882+0000 I NETWORK [js] Cannot reach any nodes for set rs0. Please check network connectivity and the status of the set. This has happened for 1 checks in a row.
等等。
感谢您的帮助和建议!
我最终使用免费版的 Atlas 进行测试和集成。一旦我的工作完成,我将在我的服务器上使用我自己的副本集。
这有点麻烦,在没有开发工具和调试器支持的情况下,我需要在生产前对所有内容进行三重检查。
我遇到了和你完全一样的问题,我已经解决了。
这是因为您的远程客户端不知道 'mongo1:27017' 主机。它仅在 docker 网络内部使用。
解释我是如何解决这个问题有点棘手。我会先展示我的docker-compose.yml。
version: "3.3"
services:
mongo-primary:
container_name: mongo-primary
hostname: mongo-primary
image: mongo:4.0.11
volumes:
- $HOME/.dockerMongoRepl/primary/data/db:/data/db
- $HOME/.dockerMongoRepl/keyfile:/data/keyfile
extra_hosts:
- "address.whichCanAccess.yourServer:192.168.1.xx"
networks:
- mongo-cluster
ports:
- 27017:27017
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: changeme
command: --bind_ip_all --auth --keyFile /data/keyfile/mongo-cluster-key --replSet rs0 --enableMajorityReadConcern false
mongo-secondary:
container_name: mongo-secondary
hostname: mongo-secondary
image: mongo:4.0.11
volumes:
- $HOME/.dockerMongoRepl/secondary/data/db:/data/db
- $HOME/.dockerMongoRepl/keyfile:/data/keyfile
depends_on:
- mongo-primary
extra_hosts:
- ""address.whichCanAccess.yourServer:192.168.1.xx""
networks:
- mongo-cluster
ports:
- 27018:27017
restart: always
command: --bind_ip_all -auth --keyFile /data/keyfile/mongo-cluster-key --replSet rs0 --enableMajorityReadConcern false
mongo-arbiter:
container_name: mongo-arbiter
hostname: mongo-arbiter
image: mongo:4.0.11
volumes:
- $HOME/.dockerMongoRepl/arbiter/data/arb:/data/arb
- $HOME/.dockerMongoRepl/keyfile:/data/keyfile
depends_on:
- mongo-primary
extra_hosts:
- ""address.whichCanAccess.yourServer:192.168.1.xx""
networks:
- mongo-cluster
ports:
- 27019:27017
restart: always
command: --bind_ip_all --auth --keyFile /data/keyfile/mongo-cluster-key --replSet rs0 --enableMajorityReadConcern false
networks:
mongo-cluster:
!重要的部分是'extra_hosts'!!它可以使容器访问主机。
"address.WhichCanAccess.yourServer" <- 在我的例子中,我的华硕路由器已经设置了华硕 ddns,所以它将是 XXX.asuscomm.com
"192.168.1.xx" <- 华硕路由器分配给主机的 IP 地址
也许不需要对那些组合文件进行某些配置。
运行 3 个容器 docker-compose.
接下来,输入主的 mongo shell,如下设置副本
config = {
"_id": "rs0",
"members": [{
"_id": 0,
"host": "address.whichCanAccess.yourServer:27017"
}, {
"_id": 1,
"host": "address.whichCanAccess.yourServer:27018"
}, {
"_id": 2,
"host": "address.whichCanAccess.yourServer:27019",
arbiterOnly: true
}]
}
rs.initiate(config)
这样,mongo容器将通过docker的主机网络相互通信,并且可以从远程IP访问。
您可以为此目的使用本地主机。撰写大致如下所示:
version: "3"
services:
mongodb:
image: mongo:4.0.11
ports:
- "27017:27017"
extra_hosts:
- "localhost:0.0.0.0"
volumes:
- "./lambda/docker/mongod.conf:/etc/mongod.conf"
然后在初始化replicaset时,确保将你的host设置为localhost。示例:
{
// ........
"members" : [
{
"_id" : 0,
"host" : "localhost:27017"
// .........
}
]
// ...........
}
已在 OSX 上测试。在 linux/windows 上它可能有不同的行为。
在我的远程机器上,我设置了一个 docker 容器机器,我使用 docker-compose 进行管理。 我为每个 MongoDB 实例创建了 3 docker 个容器,我想要在我的副本集中
mongodb_01:
image: mvertes/alpine-mongo
entrypoint: ['/usr/bin/mongod', '--bind_ip_all', '--replSet', 'rs0']
restart: always
ports:
- 10001:27017
volumes:
- ./mongodb/01:/data/db
mongodb_02:
image: mvertes/alpine-mongo
entrypoint: ['/usr/bin/mongod', '--bind_ip_all', '--replSet', 'rs0']
restart: always
depends_on:
- mongodb_01
ports:
- 10002:27017
volumes:
- ./mongodb/02:/data/db
mongodb_03:
image: mvertes/alpine-mongo
entrypoint: ['/usr/bin/mongod', '--bind_ip_all', '--replSet', 'rs0']
restart: always
depends_on:
- mongodb_02
ports:
- 10003:27017
volumes:
- ./mongodb/03:/data/db
我还配置了副本集。这是摘录:
"_id" : "rs0",
...
"members" : [
{
"_id" : 0,
"host" : "mongodb_01:27017",
...
},
{
"_id" : 1,
"host" : "mongodb_02:27017",
...
},
{
"_id" : 2,
"host" : "mongodb_03:27017",
...
}
],
...
}
一切正常,其他 docker 图像和此副本集之间的内部通信使用连接字符串正常工作
mongodb://mongodb_01:27017,mongodb_02:27017,mongodb_03:27017/<database>?replicaSet=rs0
问题是当我需要将远程客户端连接到这个副本集时。 例如,在我的开发机器上通过节点使用猫鼬,我得到:
MongoNetworkError: failed to connect to server [mongodb_02:27017] on first connect [MongoNetworkError: getaddrinfo ENOTFOUND mongodb_02 mongodb_02:27017]
有时会在 mongodb_03 上失败。
编辑:如前所述,这是我来自远程机器的连接字符串:
mongodb://<remote-host>:10001,<remote-host>:10002,<remote-host>:10003/<database>?replicaSet=rs0
编辑 2:使用像 Mongodb Compass 这样的客户端,我可以正确地成功连接到单个实例。当我添加副本集时,出现错误。 所以我尝试用mongodb(使用mongo:latest)创建一个虚拟容器。
$ docker run -it mongo:latest bash
和运行
mongo mongodb://<remote-host>:10001,<remote-host>:10002,<remote-host>:10003/<database>?replicaSet=rs0
我明白了
MongoDB shell version v4.0.6
connecting to: mongodb://<remote-host>:10001,<remote-host>:10002,<remote-host>:10003/<database>?gssapiServiceName=mongodb&replicaSet=rs0
2019-03-04T16:12:54.375+0000 I NETWORK [js] Starting new replica set monitor for rs0/<remote-host>:10001,<remote-host>:10002,<remote-host>:10003
2019-03-04T16:12:54.377+0000 I NETWORK [ReplicaSetMonitor-TaskExecutor] Successfully connected to <remote-host>:10003 (1 connections now open to <remote-host>:10003 with a 5 second timeout)
2019-03-04T16:12:54.377+0000 I NETWORK [js] Successfully connected to <remote-host>:10001 (1 connections now open to <remote-host>:10001 with a 5 second timeout)
2019-03-04T16:12:54.378+0000 I NETWORK [js] changing hosts to rs0/mongodb_01:27017,mongodb_02:27017,mongodb_03:27017 from rs0/<remote-host>:10001,<remote-host>:10002,<remote-host>:10003
2019-03-04T16:12:54.882+0000 W NETWORK [js] Unable to reach primary for set rs0
2019-03-04T16:12:54.882+0000 I NETWORK [js] Cannot reach any nodes for set rs0. Please check network connectivity and the status of the set. This has happened for 1 checks in a row.
等等。
感谢您的帮助和建议!
我最终使用免费版的 Atlas 进行测试和集成。一旦我的工作完成,我将在我的服务器上使用我自己的副本集。
这有点麻烦,在没有开发工具和调试器支持的情况下,我需要在生产前对所有内容进行三重检查。
我遇到了和你完全一样的问题,我已经解决了。
这是因为您的远程客户端不知道 'mongo1:27017' 主机。它仅在 docker 网络内部使用。
解释我是如何解决这个问题有点棘手。我会先展示我的docker-compose.yml。
version: "3.3"
services:
mongo-primary:
container_name: mongo-primary
hostname: mongo-primary
image: mongo:4.0.11
volumes:
- $HOME/.dockerMongoRepl/primary/data/db:/data/db
- $HOME/.dockerMongoRepl/keyfile:/data/keyfile
extra_hosts:
- "address.whichCanAccess.yourServer:192.168.1.xx"
networks:
- mongo-cluster
ports:
- 27017:27017
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: changeme
command: --bind_ip_all --auth --keyFile /data/keyfile/mongo-cluster-key --replSet rs0 --enableMajorityReadConcern false
mongo-secondary:
container_name: mongo-secondary
hostname: mongo-secondary
image: mongo:4.0.11
volumes:
- $HOME/.dockerMongoRepl/secondary/data/db:/data/db
- $HOME/.dockerMongoRepl/keyfile:/data/keyfile
depends_on:
- mongo-primary
extra_hosts:
- ""address.whichCanAccess.yourServer:192.168.1.xx""
networks:
- mongo-cluster
ports:
- 27018:27017
restart: always
command: --bind_ip_all -auth --keyFile /data/keyfile/mongo-cluster-key --replSet rs0 --enableMajorityReadConcern false
mongo-arbiter:
container_name: mongo-arbiter
hostname: mongo-arbiter
image: mongo:4.0.11
volumes:
- $HOME/.dockerMongoRepl/arbiter/data/arb:/data/arb
- $HOME/.dockerMongoRepl/keyfile:/data/keyfile
depends_on:
- mongo-primary
extra_hosts:
- ""address.whichCanAccess.yourServer:192.168.1.xx""
networks:
- mongo-cluster
ports:
- 27019:27017
restart: always
command: --bind_ip_all --auth --keyFile /data/keyfile/mongo-cluster-key --replSet rs0 --enableMajorityReadConcern false
networks:
mongo-cluster:
!重要的部分是'extra_hosts'!!它可以使容器访问主机。
"address.WhichCanAccess.yourServer" <- 在我的例子中,我的华硕路由器已经设置了华硕 ddns,所以它将是 XXX.asuscomm.com
"192.168.1.xx" <- 华硕路由器分配给主机的 IP 地址
也许不需要对那些组合文件进行某些配置。
运行 3 个容器 docker-compose.
接下来,输入主的 mongo shell,如下设置副本
config = {
"_id": "rs0",
"members": [{
"_id": 0,
"host": "address.whichCanAccess.yourServer:27017"
}, {
"_id": 1,
"host": "address.whichCanAccess.yourServer:27018"
}, {
"_id": 2,
"host": "address.whichCanAccess.yourServer:27019",
arbiterOnly: true
}]
}
rs.initiate(config)
这样,mongo容器将通过docker的主机网络相互通信,并且可以从远程IP访问。
您可以为此目的使用本地主机。撰写大致如下所示:
version: "3"
services:
mongodb:
image: mongo:4.0.11
ports:
- "27017:27017"
extra_hosts:
- "localhost:0.0.0.0"
volumes:
- "./lambda/docker/mongod.conf:/etc/mongod.conf"
然后在初始化replicaset时,确保将你的host设置为localhost。示例:
{
// ........
"members" : [
{
"_id" : 0,
"host" : "localhost:27017"
// .........
}
]
// ...........
}
已在 OSX 上测试。在 linux/windows 上它可能有不同的行为。