【问题标题】:Mongodb, Boot2Docker, and Replica Set connectionsMongodb、Boot2Docker 和副本集连接
【发布时间】:2015-06-26 06:26:55
【问题描述】:

我有一个 docker 容器,它充当副本集的单个成员。我能够成功启动其中的三个并在其中运行一些 shell 脚本,以便将它们连接在一起作为副本集。我发现我可以从我的主机单独连接到每个成员,但是当我尝试通过在 boot2docker IP 和相应的端口,我发现应用程序在某个地方为每个容器 IP 交换了 boot2docker IP,并尝试直接连接到该 IP。

我假设发生这种情况是因为初始连接字符串只是一个种子列表,然后实际配置是通过与成员本身的通信提供的。这当然是一个问题,因为这些 IP 不存在于主机(运行应用程序的地方)上,只存在于 boot2docker 虚拟机中。如何让成员报告 boot2docker IP 而不是他们各自无法访问的 IP?

我遇到了与 elasticsearch 类似的东西,并且能够通过设置 network.publish_host 变量来修复它。 mongodb有类似的设置吗?我认为也许 bind_ip 是正确的,但无法使其工作,我是否使用不正确?我一直将它设置为 boot2docker IP,并且在启动时收到绑定错误。

另外,我可以确认这只是 boot2docker 的问题,因为我的朋友运行 ubuntu 和本地 docker 能够正常连接。

这是我在尝试将我的 bind_ip 设置为 boot2docker vm 时看到的错误:

Starting mongod process using command: /usr/bin/mongod --storageEngine wiredTiger --auth --dbpath /data/db/ --replSet rs0 --bind_ip 127.0.0.1,192.168.59.103 --keyFile /mongodb-keyfile
2015-04-19T16:34:41.123+0000 E NETWORK  [initandlisten] listen(): bind() failed errno:99 Cannot assign requested address for socket: 192.168.59.103:27017

这是我的 spring xml 中的连接字符串:

<mongo:mongo id="mongo" replica-set="192.168.59.103:27017,192.168.59.103:27018,192.168.59.103:27019"/>

这是我的应用程序看到的错误(如果我刚刚开始工作而没有尝试更改 bind_ip 等)

Client view of cluster state is {type=ReplicaSet, servers=[{address=172.17.0.34:27017, type=Unknown, state=Connecting}, {address=172.17.0.35:27017, type=Unknown, state=Connecting}, {address=172.17.0.36:27017, type=Unknown, state=Connecting}]
        at com.mongodb.BaseCluster.getServer(BaseCluster.java:82) ~[mongo-java-driver-2.13.0.jar:na]

这些 IP 是每个容器的 IP,每个容器确实在 27017 端口上启动,但是我在 boot2docker 虚拟机上将它们的端口发布为 27017、27018 和 27019。

【问题讨论】:

    标签: mongodb docker boot2docker replicaset


    【解决方案1】:

    我在关注this tutorial to set up a mongodb cluster via docker 后遇到了类似的问题。为了能够打开与该集群的正确副本集连接,我对说明进行了以下两项修改:

    1. 我没有使用专用的 docker 网桥,而是通过使用托管网络启动每个节点(例如):

    docker run -p 30001:30001 --name mongo1 --net host mongo mongod --replSet rs1 --port 30001

    (“--net host”使用主机网络,然后必须重新映射端口以使用主机上的可用端口。不确定在此设置中是否需要端口转发选项)

    1. 我正在使用 docker 机器在 windows 上运行,所以我使用以下方法检索了 vm 的 ip:

    码头机器环境

    然后将该 IP 插入副本集配置,因此(在本例中,VM 的 IP 为 192.168.99.100):

    config = {
          "_id" : "rs1",
          "members" : [
            {
              "_id" : 0,
              "host" : "192.168.99.100:30001"
            },
            {
              "_id" : 1,
              "host" : "192.168.99.100:30002"
            },
            {
              "_id" : 2,
              "host" : "192.168.99.100:30003"
            }
          ]
        }
    

    显然,整个设置仅用于测试,并非为生产而设计。

    【讨论】:

      【解决方案2】:

      我找到了解决方案。本质上,对 mongo 客户端(在我的例子中是 spring 数据)来说重要的是副本集成员自己报告的地址。初始连接字符串只是一个种子列表,它会被遍历,直到指定成员之一以副本集配置的完整详细信息响应客户端。

      这意味着为重试尝试记录的实际 IP 以及与副本集的所有未来交互都取决于副本集在客户端请求其配置时向客户端报告的内容,该配置由副本集配置文件。

      由于副本集是使用 docker 容器 IP 启动的,这些 IP 记录在副本集配置文档中,然后在启动时报告给应用程序,因此一旦客户端切换到使用这些 IP,它就无法再使用连接到容器,因为 docker IP 没有暴露在 boot2docker VM 之外。

      解决方案(在我的情况下)是更改副本集初始配置,以提供成员 IP,就好像它是从主机启动的一样(实际上它们只是在 boot2docker 机器上公开的不同端口) .这意味着配置文档中的地址可以被我主机上的任何客户端访问,而不仅仅是 boot2docker 中的那些。

      【讨论】:

        【解决方案3】:

        您必须在容器的 IP 地址中启动您的 mongod

        试试这个:/usr/bin/mongod --auth --dbpath /data/db/ --replSet rs0 --bind_ip 172.17.0.34

        172.17.0.34 是你的容器的地址(mongod primairy)

        【讨论】:

        • mongod进程是在docker容器本身启动的,IP不应该是localhost吗?问题在于 boot2docker 将我路由到容器 IP 地址,但主机无法访问该 IP 上的容器 - 它只能直接访问 boot2docker 虚拟机。
        • mongod 进程应该从 docker 容器 ip 地址开始。默认情况下主机无法访问容器ip,所以你必须手动执行:docker run -d -p host_ip:port:27017 mongo_image,你现在可以通过host_ip:port访问容器
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-25
        • 1970-01-01
        • 1970-01-01
        • 2013-11-02
        • 2014-07-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多