Docker and mongo-go-driver "server selection error"

10,813

This is due to unresolved hostname from Docker host. In Docker, the instances mongo1, mongo2, and mongo3 are reachable by those names. However, these names are not reachable from the Docker host. This is evident by this line:

Addr: mongo2:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo2: no such host

MongoDB driver will attempt server discovery from given a replica set member(s); it will find all of other nodes within the replica set (via rs.conf). The problem here is the replica set is set with name mongo<N>, the driver (run in Docker host) would not be able to resolve these names. You can confirm this by trying to ping mongo1 from Docker host.

You can either try running the application from another Docker instance sharing the same Docker network as the replica set. Or, modify the Docker networking as such to allow resolvable hostnames.

UPDATE:

Regarding your comment on why using mongo shell, or PyMongo works.

This is due to the difference in connection mode. When specifying a single node, i.e. mongodb://node1:27017 in shell or PyMongo, server discovery are not being made. Instead it will attempt to connect to that single node (not as part as a replica set). The catch is that you need to connect to the primary node of the replica set to write (you have to know which one). If you would like to connect as a replica set, you have to define the replica set name.

In contrast to the mongo-go-driver, by default it would perform server discovery and attempt to connect as a replica set. If you would like to connect as a single node, then you need to specify connect=direct in the connection URI. See also Example Connect Direct

Share:
10,813
Lorenzo D'Isidoro
Author by

Lorenzo D'Isidoro

Updated on June 09, 2022

Comments

  • Lorenzo D'Isidoro
    Lorenzo D'Isidoro about 2 years

    I had creating a MongoDB replica set using Docker and I can access using console or Robo3T and run any query.

    The containers appear like this:

    $ docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
    efe6ae03323d        mongo               "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes       0.0.0.0:30001->27017/tcp   mongo1
    57d2701c8a43        mongo               "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes       0.0.0.0:30002->27017/tcp   mongo2
    7553966b9ff5        mongo               "docker-entrypoint.s…"   10 minutes ago      Up 10 minutes       0.0.0.0:30003->27017/tcp   mongo3
    

    The problem is an error when I try to ping using the mongo-go-driver (I tried with version 1.0.0 and 1.0.2)

    // Create MongoDB client    
    client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:30001"))
    if err != nil {
        t.Fatalf("Exit error: %v", err)
    }
    
    ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    defer cancel()
    err = client.Connect(ctx)
    if err != nil {
        t.Fatalf("Exit error: %v", err)
    }
    
    ctx, cancel = context.WithTimeout(context.Background(), time.Minute)
    defer cancel()
    
    // Ping
    err = client.Ping(ctx, readpref.Primary())
    if err != nil {
        t.Fatalf("Exit error Ping: %v", err)
    }
    

    the error raised by the Ping call is the following:

    Exit error Ping: server selection error: server selection timeout
            current topology: Type: ReplicaSetNoPrimary
            Servers:
            Addr: mongo2:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo2: no such host
            Addr: mongo3:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo3: no such host
            Addr: mongo1:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: dial tcp: lookup mongo1: no such host
    

    Thank you all for the support!

  • Lorenzo D'Isidoro
    Lorenzo D'Isidoro about 5 years
    Ok, right! But I didn't understand why, for example, with pymongo I can connect and test replica.
  • Wan B.
    Wan B. about 5 years
    With pymongo it works because when you provide only one node, Pymongo does not do server discovery. It just connect to that one node ( not as a replica set). If you would like to do the same, connect only to one node not as a replica set with mongo-go-driver, you have to specify “connect=direct”
  • Lorenzo D'Isidoro
    Lorenzo D'Isidoro about 5 years
    Ok, it's working! I will consider what's better for my case, thank you for the support
  • john
    john over 4 years
    @WanBachtiar what would happen if I use connect=direct with a connection string like this mongodb://primary:27018,secondary:27019/clickshield?replicaS‌​et=rs0&connect=direc‌​t? Is there a bad side-effect?
  • Wan B.
    Wan B. over 4 years
    @john what's the intention and purpose of specifying that URI ? feel free to open a new question instead.
  • john
    john over 4 years
    @WanBachtiar trying to access a mongo cluster replica set deployed in Kubernetes. I’m accessing from local machine or another Kubernetes cluster.