1
votes

I cannot connect to Elasticsearch docker server from my NodeJS application.

My code

This is my docker-compose file:

version: "3.7"
services:
  backend:
    container_name: vstay-api
    ports:
      - "4000:4000"
    build:
      context: .
      dockerfile: Dockerfile
    env_file:
      - ./.env
    environment:
      - DB_URI=mongodb://mongo:27017/vstay-db
      - DB_HOST=mongo
      - DB_PORT=27017
    restart: always
    links:
      - mongo
      - elasticsearch
  mongo:
    image: mongo:4.2
    ports:
      - "9000:27017"
    container_name: vstay-db
    restart: always
    volumes:
      - "./data/mongo:/data/db"
    environment:
      - DB_HOST=mongo
      - DB_PORT=27017
    command: mongod
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.9.3
    container_name: vstay_elasticsearch
    environment:
      - node.name=elasticsearch
      - cluster.name=datasearch
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - cluster.initial_master_nodes=elasticsearch
    ports:
      - 9200:9200
      - 9300:9300
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./data/elastic:/usr/share/elasticsearch/data
  kibana:
    image: docker.elastic.co/kibana/kibana:7.9.3
    container_name: vstay_kibana
    logging:
      driver: none

elastic.js

const { Client } = require("@elastic/elasticsearch");

module.exports.connectES = () => {
  try {
    const client = new Client({
      node: "http://localhost:9200",
      maxRetries: 5,
      requestTimeout: 60000,
      sniffOnStart: true,
    });

    client.ping(
      {
        // ping usually has a 3000ms timeout
        requestTimeout: Infinity,
        // undocumented params are appended to the query string
        hello: "elasticsearch!",
      },
      function (error) {
        if (error) {
          console.log(error);
          console.trace("elasticsearch cluster is down!");
        } else {
          console.log("All is well");
        }
      }
    );

    return client;
  } catch (error) {
    console.log(error);
    process.exit(0);
  }
};

And index.js to connect:

const { app } = require("./config/express");

const { connect: dbConnect } = require("./config/mongo");

const { connectES } = require("./config/elastic");

const { port, domain, env } = require("./config/vars");

let appInstance;
const startApp = async () => {
  const dbConnection = await dbConnect();
  const ESConnection = await connectES();

  app.locals.db = dbConnection;
  app.locals.ESClient = ESConnection;

  app.listen(port, () =>
    console.log(`Server is listening on ${domain.API} (${env})`)
  );

  return app;
};

appInstance = startApp();

module.exports = { appInstance };

Error

I have an application that is dockerized (NodeJS and Elasticsearch - v7.9.3). The server could be started well, but when I tried to create a Client instance in Elasticsearch, it showed me an error:

ConnectionError: connect ECONNREFUSED 127.0.0.1:9200
                            at ClientRequest.<anonymous> (/app/node_modules/@elastic/elasticsearch/lib/Connection.js:109:18)
                            at ClientRequest.emit (events.js:210:5)
                            at Socket.socketErrorListener (_http_client.js:406:9)
                            at Socket.emit (events.js:210:5)
                            at emitErrorNT (internal/streams/destroy.js:92:8)
                            at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
                            at processTicksAndRejections (internal/process/task_queues.js:80:21) {
                            name: 'ConnectionError',
                            meta: {
                            body: null,
                            statusCode: null,
                            headers: null,
                            meta: {
                              context: null,
                              request: [Object],
                              name: 'elasticsearch-js',
                              connection: [Object],
                              attempts: 5,
                              aborted: false
                            }
                          }
                         }

The server of Elasticsearch and Kibana are started, I can connect it on my browser at: http://localhost:9200 and http://localhost:5601.

But when I connect from my nodeJS app, it still shows error. I also tried to find my Container IP and replace it with 'localhost' but it still not working.

Can anyone help me to resolve this? Thanks.

My Environment

  • node version: v10.19.0
  • @elastic/elasticsearch version: 7.9.3
  • os: Linux
  • Enviroment: Docker
1
You basically need to do the same for elasticsearch as you did for mongodb. The hostname must be set to the service name of the elasticsearch instance (full URL elasticsearch:9200). For details see this answer. stackoverflow.com/a/40343492/4854965Andreas Jägle
Thanks @Andreas Jägle, It works now!Tong

1 Answers

3
votes

when you run the docker-compose file, the elasticsearch service instance will not be available to your backend service at localhost. change http://localhost:9200 to http://elasticsearch:9200 in your node.js code.

docker compose automatically creates dns entries with same name as the service name for each service.