Search code examples
mongodbdockerdocker-composedocker-network

Mongo/Compass connection issue between docker containers


I have all my services dockerized via docker-compose.yml (irrelevant lines have been omitted):

proxy:
    image: nginx:alpine    
    ports:
      - '80:80'
      - '443:443'    
    networks:
      - myNetwork

app-server:  
    ports:
      - '3000:3000'
    volumes:
      - ./:/app
      - /app/node_modules    
    networks:
      - myNetwork

mongo6:   
    networks:
      - myNetwork
    ports:
      - 27017:27017    

networks:
  myNetwork:
    external: true
    

I'm trying to connect to the mongo instance so the relevant parts of my nginx.conf are:

   upstream docker-mongo {
      server mongo6:27017;
   }


   server {
      listen 443 ssl;
      server_name mongo.mysite.co;
      ...

      location / {
         proxy_pass http://docker-mongo;
      }
   }

I created a new Mongo user mongo-mydb-user for the database "mydb"

Now I can connect to the mongo6 container from the outside world like via Compass using connection string:

mongodb://mongo-mydb-user:[email protected]:27017/mydb

However, I cannot connect to the mongo6 container from within my code (the "app-server" container) using the same connection string.

I can flip this situation around such that my code CAN connect but then Compass CAN'T. To do that, I can simply use network_mode: host instead of network: myNetwork and then modify the nginx config to proxy_pass mongo requests directly to http://localhost:27017 instead of http://docker-mongo.

Using network_mode: host isn't something I want to do. I have another machine setup exactly the same using a docker network and there is no issue connecting from either compass or app code.

My /etc/host is as follows:

127.0.0.1   localhost
::1     localhost ip6-localhost ip6-loopback
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters

# Auto-generated hostname. Please do not remove this comment.
31.123.45.678 mysite.vps.local mysite

What's wrong with my docker network configuration that I can connect via Compass but not from my app code?

The error is

Failed to connect to mongo MongooseServerSelectionError: Server selection timed out after 30000 ms
server  |     at Connection.openUri (/app/node_modules/mongoose/lib/connection.js:825:32)
server  |     at /app/node_modules/mongoose/lib/index.js:414:10
server  |     at /app/node_modules/mongoose/lib/helpers/promiseOrCallback.js:41:5
server  |     at new Promise (<anonymous>)
server  |     at promiseOrCallback (/app/node_modules/mongoose/lib/helpers/promiseOrCallback.js:40:10)
server  |     at Mongoose._promiseOrCallback (/app/node_modules/mongoose/lib/index.js:1288:10)
server  |     at Mongoose.connect (/app/node_modules/mongoose/lib/index.js:413:20)
server  |     at App.connectToDatabase (/app/dist/app.js:47:41)
server  |     at new App (/app/dist/app.js:117:18)
server  |     at main (/app/dist/server.js:42:21) {
server  |   reason: TopologyDescription {
server  |     type: 'Single',
server  |     servers: Map(1) { 'mongo.cardstop.co:27017' => [ServerDescription] },
server  |     stale: false,
server  |     compatible: true,
server  |     heartbeatFrequencyMS: 10000,
server  |     localThresholdMS: 15,
server  |     setName: null,
server  |     maxElectionId: null,
server  |     maxSetVersion: null,
server  |     commonWireVersion: 0,
server  |     logicalSessionTimeoutMinutes: null
server  |   },
server  |   code: undefined
server  | }

Solution

  • Instead of using the host as an "indirect route" to the container, you could utilize the network created by docker-compose (myNetwork) and use the service name (mongo6) to identify your container.

    As such, you could try using mongo6 as host name instead (or the reverse-proxy proxy, both should be possible with your setup). For example, in the connection string:

    mongodb://mongo-mydb-user:pass@mongo6:27017/mydb