Search code examples
spring-bootdocker-compose

Exception in monitor thread while connecting to server


I have created a docker environment which runs

  1. mongo - starts mongodb
  2. mongoimport - puts in some dummy data
  3. ordersearchservice - spring-boot microservice app
  4. productinfoservice - spring-boot microservice app
  5. userinfoservice - spring-boot microservice app

userinfoservice is the only one which needs to connect to mongodb as of now. It is supposed to fetch user-details from mongodb document. Everything is working fine if I run it outside docker container, but if I start the container, mongodb connection is not working correctly. There are two errors.

  1. Error during userinfoservice startup
Exception in monitor thread while connecting to server localhost:27017
userinfoservice-1     |
userinfoservice-1     | com.mongodb.MongoSocketOpenException: Exception opening socket
userinfoservice-1     |         at 
  1. Error while hitting the controller from postman (or even directly from browser)
userinfoservice-1     | org.springframework.dao.DataAccessResourceFailureException: Timed out after 30000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/[0:0:0:0:0:0:0:1]:27017}, caused by {java.net.ConnectException: Connection refused}}]
userinfoservice-1     |         at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:88) ~[spring-data-mongodb-4.2.5.jar!/:4.2.5]

Here are the files I am using

  1. docker-compose.yml
version: "3"

services:
  mongo:
    image: mongo
    container_name: mongodb
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: pwd
      MONGO_INITDB_DATABASE: admin

  mongoimport:
    image: mongo
    volumes:
      - ./mongo/data/users.json:/src/data/users.json
    command: mongoimport --host mongo --username root --password pwd --db admin --collection users --file /src/data/users.json --jsonArray
    depends_on:
      - mongo

  ordersearchservice:
    build:
      context: ./order-search-service
      dockerfile: Dockerfile
    image: order-search-service
    ports:
      - "8081:8081"
    depends_on:
      - mongoimport
    environment:
      SPRING_DATA_MONGODB_URI: mongodb://root:pwd@localhost:27017/admin

  productinfoservice:
    build:
      context: ./product-info-service
      dockerfile: Dockerfile
    image: product-info-service
    ports:
      - "8082:8082"
    depends_on:
      - ordersearchservice
    environment:
      SPRING_DATA_MONGODB_URI: mongodb://root:pwd@localhost:27017/admin

  userinfoservice:
    build:
      context: ./user-info-service
      dockerfile: Dockerfile
    image: user-info-service
    ports:
      - "8083:8083"
    depends_on:
      - productinfoservice
    environment:
      SPRING_DATA_MONGODB_URI: mongodb://root:pwd@localhost:27017/admin

  1. userinfoservice/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.shaan</groupId>
    <artifactId>user-info-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>user-info-service</name>
    <description>User Info service</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-reactivestreams</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-core</artifactId>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

  1. userinfoservice/Dockerfile
FROM maven:3.8.4-openjdk-17 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests

FROM openjdk:17-oracle
WORKDIR /app
COPY --from=build /app/target/user-info-service-0.0.1-SNAPSHOT.jar .
ENTRYPOINT  java -jar user-info-service-0.0.1-SNAPSHOT.jar

  1. userinfoservice/src/main/resources/application.properties
spring.application.name=user-info-service
spring.data.mongodb.uri=mongodb://root:pwd@localhost:27017/admin

searchOrderByPhoneUrl=http://localhost:8081/orderSearchService/order/phone
searchProductByProductCode=http://localhost:8082/productInfoService/product/names

server.port=8083

I have already tried below things:

  1. I thought mongodb has not started already when userinfoservice is starting, so I made it to depend on mongodb.
  2. I double checked for database connection issue, but docker is starting up mongodb perfectly fine
  3. I checked database reactive driver in pom.xml and that also looks to be in place (Not needed as application is working fine outside docker)
  4. I checked firewall. There is nothing.

But still I am not able to fetch data when the service is running in docker. Please let me know if I am missing anything. Thanks for help.


Solution

  • When running applications inside containers, each container typically has its own isolated network namespace. This means that "localhost" within a container refers to the container itself, not the host machine or other containers. So userinfoservice application can't view mongo service because 27017 port is exposed to your own local machine and visible from your own localhost but not from the container.

    By default Docker Compose you are using sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by the service's name. (https://docs.docker.com/compose/networking/)