I have a spring cloud config server and packaged it as a docker image then I have spring cloud eureka server which is also packaged as docker image.
When I run the two using docker compose I get the following error.
discovery-service_1 | 2017-06-24 15:36:12.059 INFO 5 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://config-service:9001
discovery-service_1 | 2017-06-24 15:36:12.997 WARN 5 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://config-service:9001/cls-discovery-service/default": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
Although the config service is up and running successfully, discover service still does not find it for some reason.
Docker compose file being used here is this
version: '2'
services:
config-service:
image: cloudsea/cls-config-service
ports:
- 9001:9001
expose:
- "9001"
discovery-service:
image: cloudsea/cls-discovery-service
depends_on:
- config-service
environment:
CLOUD_SEA_CONFIG_SERVER_URI: http://config-service:9001
EUREKA_DEFAULT_ZONE_URL: http://discovery-service:8761/eureka/
ports:
- 8761:8761
links:
- config-service:config-service
Below is the bootstrap.properties for DISCOVERY SERVICE
spring.cloud.config.uri = ${CLOUD_SEA_CONFIG_SERVER_URI:http://localhost:9001}
spring.application.name = ${SPRING_APPLICATION_NAME:cls-discovery-service}
Below is the cls-discovery-service.properties for DISCOVERY SERVICE located in github.
server.port=${SERVER_PORT:8761}
eureka.client.registerWithEureka: false
eureka.client.fetchRegistry: false
eureka.client.serviceUrl.defaultZone: ${EUREKA_DEFAULT_ZONE_URL:http://localhost:8761/eureka/}
eureka.server.eviction-interval-timer-in-ms: 1000
I am assuming something is wrong with my docker-compose.yml but I am not sure.
Any help will I am stick in this for hours ... heading close to days :(
Spring Cloud Config Server provides an HTTP resource-based API for external configuration (name-value pairs or equivalent YAML content). The server is embeddable in a Spring Boot application, by using the @EnableConfigServer annotation. Consequently, the following application is a config server: ConfigServer.
Now, you need to add the @RefreshScope annotation to your main Spring Boot application. The @RefreshScope annotation is used to load the configuration properties value from the Config server. Now, add the config server URL in your application. properties file and provide your application name.
Creating Spring Cloud Configuration Server Gradle users can add the below dependency in your build. gradle file. Now, add the @EnableConfigServer annotation in your main Spring Boot application class file. The @EnableConfigServer annotation makes your Spring Boot application act as a Configuration Server.
Spring Cloud Config is Spring's client/server approach for storing and serving distributed configurations across multiple applications and environments. This configuration store is ideally versioned under Git version control and can be modified at application runtime.
I solved it by adding this configuration to the discovery service's bootstrap.yml.
spring:
cloud:
config:
failFast: true
retry:
initialInterval: 3000
multiplier: 1.3
maxInterval: 5000
maxAttempts: 20
Then add spring-boot-starter-aop and spring-retry to the discovery service's maven dependencies.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${spring-boot-starter-aop.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${spring-retry.version}</version>
</dependency>
The problem is they're both starting at the same time. But the discovery service depends on the config service.
When you start the discovery service, it's going to say "Fetching config from server" again and again until config service is up.
After the config service starts, discovery service is going to get its configuration successfully and then it's going to start itself.
The problem is all the docker container will start together, but as per your architecture, the config-service needs to start first, then the discovery-service(eureka). So discovery-service is giving the error.
depends_on
does not wait for config-service to be “ready” before starting discovery-service - it only waits until it is started. If you need to wait for a service to be ready, you have to use controlling startup order.
As suggested about you can set the APIs/Services to keep retrying in some intervals until the config server is up.
Although, I would also prefer to use depends_on or healthcheck and controlling startup order as shown below:
version: "2"
services:
web:
build: .
ports:
- "80:8000"
depends_on:
- "db"
command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]
db:
image: postgres
wait-for-it.sh is a pure bash script that will wait on the availability. I would also suggest looking into, container orchestration tools like docker-swarm or kubernetes.
I've faced the same issue and was stuck for a bit and I was about to go the same route as you did with the spring retry, which isn't a bad pattern to follow it does embed resiliency into your application but the main issue here is docker's launch order is out of place. I'll share my working docker-compose file, it's quite similar but the key here is the "depends_on" parameter. I've added quotes on my arguments and it seemed to work.
version: "2"
services:
eureka:
image: eurekatest
ports:
- "8761:8761"
config:
image: config
ports:
- "8888:8888"
links:
- eureka:eureka
depends_on:
- "eureka"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With