Can't connect to Mongo Docker Container From Node Container on M1 Mac
Asked Answered
A

4

5

I am currently trying to connect my Node container to my Mongo container using an M1 chip. Many have said that you can't run Mongo 4.9+ on an M1 Mac as there is no support for AVR. I can't say why but on my M1 mongo runs just fine. I can connect to the container via Mongo Compass using mongo://mongo:27017. Additionally if I run my Node app outside of docker I can connect to the Mongo container just fine using the same connection string. But for some reason I cannot connect the containerized node app to the containerized Mongo service.

Dockerfile

 FROM node:12

# Create app directory
WORKDIR /usr/src/app

# Copy dependencies 
COPY package*.json ./

# Install dependencies 
RUN npm install

RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 3000
CMD [ "node", "server.js" ]

docker-compose.yml

version: "2"
services:
  web:
    build: .
    ports:
    - "3000:3000"
    depends_on:
    - mongo
  mongo:
    image: mongo
    ports:
    - "27017:27017"

Connection Method

/* Mongoose Connection */
const mongoose = require('mongoose')

mongoose.Promise = global.Promise
mongoose.connect(
  'mongodb://mongo:27017',
  { useNewUrlParser: true }
)
mongoose.connection.on('error', console.error.bind(console, 'MongoDB connection 

Error:'))

mongoose.set('debug', true)

module.exports = mongoose.connection

server.js

require('dotenv').config();
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const expressValidator = require('express-validator')
var cookieParser = require('cookie-parser');
const jwt = require('jsonwebtoken');
app.use(cookieParser()); // Add this after you initialize express.


// db
require('./data/reddit-db')

// set db
const exphbs = require('express-handlebars')

// body parser
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(expressValidator())

app.engine('handlebars', exphbs({ defaultLayout: 'main' }))
app.set('view engine', 'handlebars')


var checkAuth = (req, res, next) => {
  console.log("Checking authentication");
  if (typeof req.cookies.nToken === "undefined" || req.cookies.nToken === null) {
    req.user = null;
  } else {
    var token = req.cookies.nToken;
    var decodedToken = jwt.decode(token, { complete: true }) || {};
    req.user = decodedToken.payload;
  }

  next();
};
app.use(checkAuth);

// routes
require('./controllers/posts.js')(app)

require('./controllers/comments.js')(app)

require('./controllers/auth.js')(app)

require('./controllers/replies.js')(app)




// Start Server
app.listen(3000, () => {
  console.log('Reddit Search listening on port localhost:3000!');
});

module.exports = app

Error

redditjspart2-web-1    | Reddit Search listening on port localhost:3000!
redditjspart2-web-1    | MongoDB connection Error: { MongoNetworkError: failed to connect to server [127.0.0.1:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]
redditjspart2-web-1    |     at Pool.<anonymous> (/usr/src/app/node_modules/mongoose/node_modules/mongodb/lib/core/topologies/server.js:438:11)
redditjspart2-web-1    |     at Pool.emit (events.js:198:13)
redditjspart2-web-1    |     at createConnection (/usr/src/app/node_modules/mongoose/node_modules/mongodb/lib/core/connection/pool.js:561:14)
redditjspart2-web-1    |     at connect (/usr/src/app/node_modules/mongoose/node_modules/mongodb/lib/core/connection/pool.js:994:11)
redditjspart2-web-1    |     at makeConnection (/usr/src/app/node_modules/mongoose/node_modules/mongodb/lib/core/connection/connect.js:31:7)
redditjspart2-web-1    |     at callback (/usr/src/app/node_modules/mongoose/node_modules/mongodb/lib/core/connection/connect.js:264:5)
redditjspart2-web-1    |     at Socket.err (/usr/src/app/node_modules/mongoose/node_modules/mongodb/lib/core/connection/connect.js:294:7)
redditjspart2-web-1    |     at Object.onceWrapper (events.js:286:20)
redditjspart2-web-1    |     at Socket.emit (events.js:198:13)
redditjspart2-web-1    |     at emitErrorNT (internal/streams/destroy.js:91:8)
redditjspart2-web-1    |     at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
redditjspart2-web-1    |     at process._tickCallback (internal/process/next_tick.js:63:19)
redditjspart2-web-1    |   name: 'MongoNetworkError',
redditjspart2-web-1    |   [Symbol(mongoErrorContextSymbol)]: {} }

What I Have Tried:

  • Running the same repo on an intel mac (works flawlessly)
  • Changing the connection string IP (mongo, localhost, 127.0.0.1)
  • Using a docker network with the bridge driver and using the assigned ip in the connection string
  • pinging mongo from inside Node container (this works and all packets are received)

The error says that it's trying to connect to 127.0.0.1:27017 which means it is properly resolving the hostname and mapping it to my localhost. So the Node container is definitely able to find it. This also makes sense because I can still ping the Mongo container from the Node container as I mentioned earlier. Looks like Mongo is just refusing to connect for some reason.

I am really struggling to figure out why this would be the case. The link to my repo is public and you can find it on github here: https://github.com/lukeaparker/reddit.jspart2

Thanks so so much!!

Apostrophize answered 5/5, 2022 at 5:31 Comment(2)
failed to connect to server [127.0.0.1:27017] Somehow your node container tries to connect to itself (127.0.0.1), this is not the right IP of your mongodb container. The name resolution seems not to work. "mongo" should resolve to something else than the subnet 127.0.0.0/8Sinkage
Actually it is resolving properly as I said above. The same code works now using a new base image. I changed FROM node:12 to FROM --platform=linux/amd64 node:10-alpine and it works fine (no connection issues). So for all intensive purposes this issue is fixed. But I am curious why the node:12 image would prevent me from connecting to mongo. I feel like it's less of a solution and more of a work around. Is there anyone that can explain this behavior, and perhaps prepose a solution that's a little more concrete?Apostrophize
K
6

I had a similar issue with the M1 Mac and managed to resolve it by putting these configs in docker-compose.yml:

services:
  mongodb:
    image: arm64v8/mongo:4.0
    platform: linux/arm64/v8

I also use docker build --platform linux/arm64/v8 and docker run --platform linux/arm64/v8 via CLI for platform explicitness since I got this warning previously:

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

Kyles answered 28/9, 2022 at 23:54 Comment(1)
This looks like you're using a MongoDB 4.0 version which went end of life April 2022 (mongodb.com/support-policy/lifecycles)Yell
G
1

I had the same issue.

As I see the issue is only with mongo 5+.

I was trying the downgrade the mongo image to

image: mongo:4.4.14

Germangermana answered 20/6, 2022 at 8:36 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Levitate
Y
0

Per https://jira.mongodb.org/browse/SERVER-50115, there are some dependancies needed before MongoDB can build a image for Mac M1/M2.

Per MongoDB engineer. Trying to run the Linux x86_64 binaries in Docker on M1, which will be problematic because of the requirement for AVX support in MongoDB 5.0 packages for Linux x86_64. The solution for the original question would be to either install MongoDB 4.4 packages on Linux (since those are not optimised for AVX) or to build MongoDB 5.x from source with an older x86_64 CPU architecture target.

Yell answered 22/2, 2023 at 6:44 Comment(0)
S
0

Use this docker-compose configuration, it is working ok on M1:

version: '3.1'

services:

  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 3001:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: example
      ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/
Snifter answered 3/3, 2023 at 21:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.