Spring boot app fail to link consul in docker

I am trying to use Consul as discovery service, and another two spring boot app to register with Consul; and put them into docker;

following are my codes:
app:

  • Connecting to a Remote EJB Module running in Docker
  • MySQL in Docker on Windows: World-writable files ignored
  • How to access host DB from Docker container?
  • Running uv4l inside Docker Container - not registering device node
  • Start only one service in a docker-compose.yml with ansible docker_service module
  • Multiple docker compose environments for same code base
  • server:
      port: 3333
    
    spring:
      application:
        name: adder
      cloud:
        consul:
          host: consul
          port: 8500
          discovery:
            preferIpAddress: true
            healthCheckPath: /health
            healthCheckInterval: 15s
            instanceId: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    

    2 docker-compose.yml

     consul1:
      image: "progrium/consul:latest"
      container_name: "consul1"
      hostname: "consul1"
      command: "-server -bootstrap -ui-dir /ui"
     adder:
      image: wsy/adder
      ports:
       - "3333:3333"
     links:
       - consul1
     environment:
       WAIT_FOR_HOSTS: consul1:8500
    

    There is another similar question Cannot link Consul and Spring Boot app in Docker;
    the answer suggests, the app should wait for consul to fully work by using depends_on, which I tried, but didn’t work;

    the error message is as following:

    adder_1    | com.ecwid.consul.transport.TransportException: java.net.ConnectException: Connection refused
    adder_1    |    at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:80) ~[consul-api-1.1.8.jar!/:na]
    adder_1    |    at com.ecwid.consul.transport.AbstractHttpTransport.makeGetRequest(AbstractHttpTransport.java:39) ~[consul-api-1.1.8.jar!/:na]
    

    besides spring boot application.yml and docker-compose.yml, following is App’s Dockerfile

    FROM java:8
    
    VOLUME /tmp
    ADD adder-0.0.1-SNAPSHOT.jar app.jar
    RUN bash -c 'touch /app.jar'
    ADD start.sh start.sh
    RUN bash -c 'chmod +x /start.sh'
    EXPOSE 3333
    ENTRYPOINT ["/start.sh", " java -Djava.security.egd=file:/dev/./urandom    -jar /app.jar"]
    

    and the start.sh

    #!/bin/bash
    
    set -e
    
    wait_single_host() {
      local host=$1
      shift
      local port=$1
      shift
    
      echo "waiting for TCP connection to $host:$port..."
    
      while ! nc ${host} ${port} > /dev/null 2>&1 < /dev/null
      do
        echo "TCP connection  [$host] not ready, will try again..."
        sleep 1
     done
    
      echo "TCP connection ready. Executing command [$host] now..."
    }
    
     wait_all_hosts() {
      if [ ! -z "$WAIT_FOR_HOSTS" ]; then
       local separator=':'
       for _HOST in $WAIT_FOR_HOSTS ; do
          IFS="${separator}" read -ra _HOST_PARTS <<< "$_HOST"
          wait_single_host "${_HOST_PARTS[0]}" "${_HOST_PARTS[1]}"
        done
       else
         echo "IMPORTANT : Waiting for nothing because no $WAIT_FOR_HOSTS env var defined !!!"
       fi
      }
    
      wait_all_hosts
    
      exec $1
    

  • How do I keep IPs in a dockerized Consul cluster on a single node after restart
  • using ansible for provisioning docker containers
  • Connection to remote host via docker-machine fails
  • Intranet name resolution in docker container
  • Run docker mongo with read-only fs
  • How to apply kernel tuning on docker container
  • 3 Solutions collect form web for “Spring boot app fail to link consul in docker”

    I can infer that your Consul configuration is located in your application.yml instead of bootstrap.yml, that’s the problem.

    According to this answer, bootstrap.yml is loaded before application.yml and Consul client has to check its configuration before the application itself and therefore look at the bootstrap.yml.

    Example of a working bootstrap.yml :

    spring:
      cloud:
        consul:
          host: consul
          port: 8500
          discovery:
            prefer-ip-address: true
    
    1. Run Consul server and do not forget the name option to match with your configuration:

      docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap

    2. Consul server is now running, run your application image (builded previously with your artifact) and link it to the Consul container:

      docker run -d -name=my-consul-client-app --link consul:consul acme/spring-app

    Your problem is that depends_on does only control the startup order of your services. You have to wait until the consul servers are up and running before starting your spring app. You can do this with this script:

    #!/bin/bash
    
    set -e
    
    default_host="database"
    default_port="3306"
    
    host="${2:-$default_host}"
    port="${3:-$default_port}"
    
    echo "waiting for TCP connection to $host:$port..."
    
    while ! (echo >/dev/tcp/$host/$port) &>/dev/null
    do
      sleep 1
    done
    
    echo "TCP connection ready. Executing command [$1] now..."
    
    exec $1
    

    Usage in you docker file:

    COPY wait.sh /wait.sh
    RUN chmod +x /wait.sh
    CMD ["/wait.sh", "java -jar yourApp-jar" , "consulURL" , "ConsulPort" ]
    

    I just want to clarify that, at last I still don’t have a solution, and can’t understand the situation here; I tried the suggestion from Ohmen, in APP container, I am able to ping consul1; But the APP still fails to connect consul;

    If I only start the consul by following command:

    docker-compose -f docker-compose-discovery.yml up discovery
    

    Then I can run the APP directly(through Main), and it is able to connect with spring.cloud.consul.host: discovery;

    But if I try to run APP in docker container, like following:

    docker run --name adder --link discovery-consul:discovery wsy/adder
    

    It fails again with connection refused;

    I am very new to docker & docker-compose; I thought it would be a good example to start, but it seems not that easy for me;

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.