简体   繁体   中英

How do I connect my mongo database to my node app with this mongoDB connection string using docker-compose?

This is a part of my node app

app.configure('development', function() {
  app.set('db-uri', 'mongodb://localhost/nodepad-development');
  app.use(express.errorHandler({ dumpExceptions: true }));
  app.set('view options', {
    pretty: true
  });
});

app.configure('test', function() {
  app.set('db-uri', 'mongodb://localhost/nodepad-test');
  app.set('view options', {
    pretty: true
  });  
});

app.configure('production', function() {
  app.set('db-uri', 'mongodb://localhost/nodepad-production');
});

Edited to

app.set('db-uri', 'mongodb://mongoDB:27017/nodepad-development');

Still the same error. I have already created container for my node app which runs on local host but I am unable to connect it to another mongo container due to which I cannot do POST requests to the app.

This is my docker compose file

version: '3'
services:
  apptest:
    container_name: apptest
    restart: always
    image: ekamzf/nodeapp:1.1
    ports:
      - '8080:8080
    depends_on:
          - mongoDB

  mongoDB:
    container_name: mongoDB
    image: mongo
    volumes:
      - ./data:/usr/src/app
    ports:
      - '27017:27017'  

And the error I get when I try to register account details in my node app is

Error: Timeout POST /users
    at null._onTimeout (/usr/src/app/node_modules/connect-timeout/index.js:12:22)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

What am I missing? Basically, how should I connect this type of code with mongodb anyway ? What's the role of 'db-uri'?

Docker Compose aliases service names to host names.

Because you named your container running the mongo image as mongoDB , mongodb (case insensitive) will be the name of the host and the name by which you should refer to it from your Node.JS container and app.

  1. Replace localhost in the URI with mongodb

The MongoDB database defaults to port 27017. Unless you've changed the port, you should specify this value.

  1. Add the port to URI so that you have mongodb:27017

  2. Optional but good practice , refactor the app to use environment variables rather than hard-coded values.

This has at least 2 benefits:

a. Your code becomes more flexible; b.Your Compose file, by then specifying these values, will be clearer.

See the DockerHub documentation for the image here

See MongoDB"s documentation on connection strings here

A Google search returns many examples using Compose, MongoDB and Node.JS

Update: repro

I'm confident your issue may be related to the timing of the Compose containers. I believe your app tries to connect to the DB before the DB container is ready. This is a common issue with Compose and is not solved using Compose's depends_on . Instead you must find a MongoDB (or perhaps other database) solution to this.

In my repro, index.js (see below) introduces a false delay before it tries to connect to the database. 5 seconds is sufficient time for the DB container to be ready and thus this works:

docker-compose build --no-cache
docker-compose up

Then:

docker-compose logs app
Attaching to 60359441_app_1
app_1            | URL: mongodb://mongodb:27017/example
app_1            | Connected

yields Connected which is good.

Alternatively, to prove the timing issue, you may run the containers separately (and you could remove the sleep function to ensure the database is ready before the app:

HOST=localhost  # No DNS naming
PORT=37017      # An arbitrary port to prove the point

# In one session
docker run \
--interactive --tty --rm \
--publish=${PORT}:27017 \
mongo

# In another session
docker run \
--interactive --tty --rm \
--net=host \
--env=HOST=${HOST} --env=PORT=${PORT} --env=DATA=example --env=WAIT=0 \
app
URL: mongodb://localhost:37017/example
Connected

docker-compose.yaml:

version: "3"

services:
  app:
    image: app
    build:
      context: ./app
      dockerfile: Dockerfile
    environment:
      - HOST=mongodb
      - PORT=27017
      - DATA=example
      - WAIT=5000
    volumes:
      - ${PWD}/app:/app

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

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_SERVER: mongodb
      # ME_CONFIG_MONGODB_ADMINUSERNAME: root
      # ME_CONFIG_MONGODB_ADMINPASSWORD: example

NB Because I followed your naming of mongodb , the mongo-express container must be provided this host name through ME_CONFIG_MONGODB_SERVER

NB The other environment variables shown with mongo and mongo-express images are the defaults and thus optional.

Dockerfile:

FROM node:13.8.0-slim

WORKDIR /usr/src/app

COPY package.json .
RUN npm install

COPY . .

ENTRYPOINT ["node","index.js"]

index.js:

// Obtain config from the environment
const HOST = process.env.HOST;
const PORT = process.env.PORT;
const DATA = process.env.DATA;
const WAIT = parseInt(process.env.WAIT, 10);

// Create MongoDB client
var MongoClient = require("mongodb").MongoClient;

let url = `mongodb://${HOST}:${PORT}/${DATA}`;
console.log(`URL: ${url}`);

// Artificially delay the code
setTimeout(function() {
  MongoClient.connect(url, function(err, db) {
    if(!err) {
      console.log("Connected");
    }
  });
}, WAIT);

NB index.js uses the environment ( HOST , PORT , DB ) for its config which is good practice.

Including mongo-express provides the ability to browse the mongo server to readily observe what's going on:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM