Spring Config server not reachable with docker-compose until client is restarted Spring Config server not reachable with docker-compose until client is restarted docker docker

Spring Config server not reachable with docker-compose until client is restarted


Being purist the answer to your question is NO, it is not an acceptable solution, because as it is stated here, Docker removed healthcheck from v3 on for some reason:

Docker have made a conscious decision not to support features that wait for containers to be in a "ready" state. They argue that applications depending on other systems should be resilient to failure.

In the same link, it is described why:

The problem of waiting for a database (for example) to be ready is really just a subset of a much larger problem of distributed systems. In production, your database could become unavailable or move hosts at any time. Your application needs to be resilient to these types of failures.

To handle this, your application should attempt to re-establish a connection to the database after a failure. If the application retries the connection, it should eventually be able to connect to the database.

Basically then, there are three options:

  1. Use v2.1 with healhcheck. See an example here
  2. Use v3 and a tool like wait-for-it ordockerize as @ortomala-lokni already perfectly explained
  3. Make your application resilient to config-server failure and able config-client to retry the connection on startup

The recommended and acceptable solution is 3). You can use Spring Retry as it is mentioned here. Find below the bootstrap.yml configuration:

spring:  application:    name: config-client  profiles:     active: dev  cloud:    config:     discovery:       enabled: true       service-id: config-server     fail-fast: true     retry:       initial-interval: 1500       multiplier: 1.5       max-attempts: 10000       max-interval: 1000eureka:  instance:    hostname: config-client  client:    registerWithEureka: true    fetchRegistry: true    serviceUrl:      defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka}

BTW I found an error in your spring configuration. It is fail-fast and not fast-fail.

Remember to include the following dependencies (or similar if you are using gradle):

<dependency>    <groupId>org.springframework.retry</groupId>    <artifactId>spring-retry</artifactId></dependency>

You can find a very well configuration (and explanation) here taking also into account resiliency during the registering process in the Eureka Server.

When having a microservices environment we must think of the resiliency of our environment when platform services like config-service, discovery-service are not available for a short period of time.

But I am not a purist at all and I would not have removed some functionality people is using (it is a question of freedom). So, an alternative solution is:

If it is working for you, then go ahead

Because I do not really understand why Docker suppressed the fantastic healthcheck command from v3.


The best solution is probably, as Carlos Cavero said, to make your application resilient to config-server failure. But you can also solve the problem by using the wait-for script from Eficode on Github.

Copy the script into your container and in your docker-compose.yml use:

client:    image: client-server:latest    environment:      JAVA_OPTS: -DEUREKA_SERVER=http://eureka:8761/eureka    depends_on:      - config    ports:      - 9000:9000    command: wait-for $CONFIGSERVER_SERVICE_NAME:$CONFIGSERVER_PORT -- java $JVM_OPTIONS -jar client.war $SPRING_OPTIONS

The environment variables for CONFIGSERVER_SERVICE_NAME and CONFIGSERVER_PORT can be defined in your Docker Compose environment file.

If you need to wait for multiple services, you can merge this pull request and list all needed services in the command line parameters such as:

command: wait-for $SERVICE1_NAME $SERVICE1_PORT $SERVICE2_NAME $SERVICE2_PORT -- java $JVM_OPTIONS -jar client.war $SPRING_OPTIONS


Service dependency are always tricky when using docker-compose.

Your solution is acceptable because "there is no other way".To avoid third-part libs, this is what I do in the same scenario:

In the Dockerfile I add netcat-openbsd, a bash file I call entrypoint and the application jar and then I run the entrypoint.sh.

FROM openjdk:8-jdk-alpineRUN apk --no-cache add netcat-openbsdCOPY entrypoint.sh /opt/bin/COPY app.jar /opt/lib/RUN chmod 755 /opt/esusab-bi/bin/app/entrypoint.sh

The entrypoint file has the following instruction:

#!/bin/shwhile ! nc -z config 8888 ; do    echo "Waiting for upcoming Config Server"    sleep 2donejava -jar /opt/lib/app.jar

It will delay the application start-up until your config server is up, without a specific interval.