1
votes

I have a Eureka Server, Config Server and Spring-Boot Service. I have created a docker compose file like this:

version: '3'

services:
 user-service:
   container_name: user-service-container
   image: user-service:latest
   build:
     context: ./user-service
     dockerfile: DockerFile
   hostname: user-service
   ports:
     - "8082:8082"
   depends_on:
      - postgresdb
      - eureka-service
      - config-server
   environment:
       management.context-path : /userservice
       hostName : user-service
       EUREKA_HOST: eureka-service
       EUREKA_PORT: 8761

 config-server:
   container_name: config-server-container
   image: config-server:latest
   build:
    context: ./config-server
    dockerfile: DockerFile
   hostname: config-server
   ports:
     - "8081:8081"
   depends_on:
       - eureka-service
   environment:
     management.context-path : /config
     hostName : config-server
     SPRING_PROFILES_ACTIVE : registration-first
     EUREKA_HOST: eureka-service
     EUREKA_PORT: 8761

 eureka-service:
   container_name: eureka-service-container
   image: eureka-service:latest
   build:
      context: ./eureka-service
      dockerfile: DockerFile
   hostname: eureka-service
   ports:
     - "8761:8761"

 postgresdb:
   container_name: postgres-db-container
   image: postgres:10.5
   hostname: postgres
   ports:
     - "5432:5432"

With this configuration Config Server can register itself to Eureka Server, however configuration part of the User Service throws below exception:

2018-09-07T18:53:17.869040200Z 2018-09-07 18:53:17.868  INFO 6 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8888
2018-09-07T18:53:18.331651100Z 2018-09-07 18:53:18.331  INFO 6 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://localhost:8888. Will be trying the next url if available
2018-09-07T18:53:18.332055700Z 2018-09-07 18:53:18.331  WARN 6 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/user-service/registered-config-server,dev": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
2018-09-07T18:53:18.334406300Z 2018-09-07 18:53:18.334  INFO 6 --- [           main] c.k.d.u.UserServiceApplication           : The following profiles are active: registered-config-server,dev
2018-09-07T18:53:18.371334800Z 2018-09-07 18:53:18.370  INFO 6 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@4d1c00d0: startup date [Fri Sep 07 18:53:18 UTC 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@13969fbe

From this exception, I understand that User Service connects to Euroka Server but it tries to connect to Config Server via a wrong URL (i.e. http://localhost:8888 )

Euroka Server App Properties:

spring.application.name=eureka-server
server.port=8761

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

Config Server App Properties:

    spring:
  cloud:
    config:
      server:
        git :
          uri: https://bitbucket.org/blabla
          username: blabla
          password: ***
      discovery:
        enabled: true
        service-id: config-server
server:
  port: 8081
---
spring:
  application:
    name: config-server
  profiles: registration-first
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/
  instance:
    appname: config-server
    hostname: ${hostName}
    statusPageUrlPath: ${management.context-path}/info
    healthCheckUrlPath: ${management.context-path}/health
    preferIpAddress: true
    metadataMap:
      instanceId: ${spring.application.name}:${server.port}

User Service Application Properties:

endpoints:
  enabled: false
  info:
    enabled: true
  health:
    enabled: true
  metrics:
    enabled: true
  refresh:
    enabled: true

eureka:
  client:
    fetchRegistry: true
    registerWithEureka: true
    serviceUrl:
      defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/
  instance:
    hostname: ${hostName}
    statusPageUrlPath: ${management.context-path}/info
    healthCheckUrlPath: ${management.context-path}/health
    preferIpAddress: true
    metadataMap:
      instanceId: ${spring.application.name}:${server.port}

spring.jpa.database: POSTGRESQL
spring.datasource.platform: postgres
spring.jpa.show-sql: true
spring.jpa.hibernate.ddl-auto: update
spring.database.driverClassName: org.postgresql.Driver
spring.datasource.url: jdbc:postgresql://postgresdb:5432/postgres
spring.datasource.username: postgres
spring.datasource.password: postgres

User Service Bootstrap.yml:

    spring:
  profiles:
    active: registered-config-server,dev
  application:
    name: user-service

server.port: 8082
---
spring:
  profiles: known-config-server
  cloud:
    config:
      uri: http://localhost:8080

---
spring:
  profiles: registered-config-server
  cloud:
    config:
      discovery:
        enabled: true
        serviceId: config-server

But when I run these applications on my local PC without docker they work properly.

Does anyone have any suggestions?

EDIT: UserService Docker File:

FROM java:8
EXPOSE 8082
ADD /target/user-service-0.0.1-SNAPSHOT.jar user-service.jar
CMD java -jar user-service.jar

config-server docker file

FROM java:8
EXPOSE 8081
ADD /target/config-server-0.0.1-SNAPSHOT.jar config-server.jar
CMD java -jar config-server.jar

eureka-server docker file

FROM java:8
EXPOSE 8761
ADD /target/eureka-service-0.0.1-SNAPSHOT.jar eureka-service.jar
CMD java -jar eureka-service.jar
3
can you format the all configurations such as Config Server App Properties, also please paste the content of Dockerfileclevertension
Without docker, localhost means the host; with docker, localhost means the container, so it's different for each container.Constantin Galbenu
You should set spring.application.name environment variable accordingly for each service (user and config) in each service environment. In this way the eureka client register itself correctly. I.e. for user service, this should be user-service, the hostname of this service in the docker network.Constantin Galbenu
Config Server App Properties: should be yaml, but your format is chaosclevertension
I am facing the same issue. I have one dockerized microservice which is required to fetch configurations from the config server. When using docker-compose, it behaves intermittently. When run alone using boot maven plugin to run all the services (config server, eureka registry, zuul proxy and microservice), it behaves perfectly fine. I suspect the issue is related to config server not being ready when accessed by microservice via eureka registry service. Please share if this has been resolved.Hammad Dar

3 Answers

3
votes

I am too facing the same issue when trying to fetch configurations from Spring Cloud Config Server running in a Docker container. My Spring Boot app tries to access it on http://localhost:8888 even though I have specified the docker container name in the app's application.proprties.

Below is my app's application.properties:

spring.application.name=stock-app
spring.profiles.active=default
spring.cloud.config.uri=http://configserver:8888
server.port=8301

As a workaround, I am passing config server URL as a parameter in my docker compose.

This is my docker-compose.yml:

version: '2'
services:
  configserver:
    image: himarg/config-server:0.0.1-SNAPSHOT
    ports:
       - "8888:8888"
    environment:
      ENCRYPT_KEY:       "IMSYMMETRIC"

  database:
    image: himarg/stock-db:latest
    ports:
      - "3307:3306"
    environment:
      MYSQL_ROOT_PASSWORD: "Welcome1"
      MYSQL_DATABASE: "inventory"

  stockapp:
    image: himarg/stock-app:0.0.1-SNAPSHOT
    ports:
      - "8301:8301"
    environment:
      PROFILE: "default"
      CONFIGSERVER_URI: "http://configserver:8888"
      CONFIGSERVER_PORT:   "8888"
      DATABASESERVER_PORT: "3306"
      ENCRYPT_KEY:       "IMSYMMETRIC"

Then I use this parameter in my shell script that I use to start my app.

Below are the Dockerfile and the script:

Dockerfile

FROM openjdk:8-jdk-alpine
RUN apk update && apk upgrade && apk add netcat-openbsd
RUN mkdir -p /usr/local/stock-app
ADD @[email protected] /usr/local/stock-app/
ADD run.sh run.sh
RUN chmod +x run.sh
CMD ./run.sh

run.sh

#!/bin/sh

echo "********************************************************"
echo "Waiting for the database server to start on port $DATABASESERVER_PORT"
echo "********************************************************"
while ! `nc -z database $DATABASESERVER_PORT`; do sleep 3; done
echo "******** Database Server has started "

echo "********************************************************"
echo "Waiting for the configuration server to start on port $CONFIGSERVER_PORT"
echo "********************************************************"
while ! `nc -z configserver $CONFIGSERVER_PORT`; do sleep 3; done
echo "*******  Configuration Server has started"

echo "********************************************************"
echo "Starting stock-app "
echo "********************************************************"
java -Dspring.cloud.config.uri=$CONFIGSERVER_URI -jar /usr/local/stock-app/@[email protected]

After making this change, I am able to successfully run my app, though I am not sure if this kind of workaround suits your requirement.

1
votes

Change this

eureka:
  client:
    fetchRegistry: true
    registerWithEureka: true
    serviceUrl:
      defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/

To this

eureka:
  client:
    fetchRegistry: true
    registerWithEureka: true
    serviceUrl:
      defaultZone: http://${EUREKA_HOST:localhost}:${EUREKA_PORT:8761}/eureka/

You also have to create a bridge network so that your apps can talk to each other. Think of dockerizing your apps as running each of the services on different computers. That means using "localhost" won't really help you.

Like this one below (source: https://developer.okta.com/blog/2017/10/11/developers-guide-to-docker-part-3)

services:
  app:
    image: sample:1.0
    container_name: sample_app
    build: .
    ports:
      - 80:3000
    environment:
      - MONGO_URI=mongodb://sampledb/sample
    depends_on:
      - db
    networks:
      - samplenet
  db:
    image: mongo:3.0.15
    container_name: sample_db
    volumes:
      - ./db:/data/db
    networks:
      samplenet:
        aliases:
          - "sampledb"
networks:
  samplenet:
    driver: bridge
1
votes

Try moving eureka.client properties to bootstrap.yml instead of application.properties for config server