Search code examples
springgradledockernetflix-eurekaconnection-refused

Connection refused on spring-client with docker and gradle


I build a spring-server and a spring-client with eureka on docker and I try to connect the client to the server. When I try this in my build.gradle:

docker {
  maintainer = 'Me'
  baseImage = 'java:8'
}

distDocker {
  exposePort 8080
  setEnvironment 'JAVA_OPTS', '-Dspring.profiles.active=docker'
}

everything works.

But I want to use the Dockerfile I wrote, so I use buildDocker instead of distDocker and I use it this way:

task buildDocker(type: Docker, dependsOn: build) {
  dockerfile = file('src/main/docker/Dockerfile')
  doFirst {
    copy {
      from jar
      into stageDir
    }
  }
}

with this Dockerfile:

FROM java:8
ADD myjar-1.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]

and that always leads to a

connection refused-error or more precisely to a ClientHandleException: Connection to http://localhost:8761 refused

I don't really understand where the problem is? If I don't try to connect to the server both ways work but if I try to connect only distDocker works.


Solution

  • The Spring Boot client app, running inside the container, is trying to reach localhost:8761, and since in the context of this Docker container 'localhost' refers to the container's address. There's nothing running on port 8761 of the container and hence you are seeing the connection refused error.

    This might help:

    Specify the location of Eureka in your client app's configuration via its application.yml:

    eureka:
      client:
        serviceUrl:
          defaultZone: <IP-address-of-Eureka-server>/eureka/
    

    The <IP-address-of-Eureka-server> can be either an IP address or a host name that can be resolved from inside the container. If you want to pass the address of your host VM (the host that runs your Docker container), you can pass it as an environment variable using --env eureka.client.serviceUrl.defaultZone=xx.xx.xx.xx form. Something like this:

    $ docker run ... --env eureka.client.serviceUrl.defaultZone=xx.xx.xx.xx
    

    On a related note, if your Spring Boot client application also needs to register itself with Eureka, then you will need additional configuration to publish the resolvable host name and port of your Spring Boot app to Eureka. You can add the following to your application.yml:

    eureka:
      instance:
        hostname: <client-host>
        nonSecurePort: <client-port>
    

    Where, <client-host> is the resolvable host name of the client app container; and <client-port> is the host VM's port that's bound to the exposed port of the container>

    Again, you can pass these using the --env argument as shown above.

    $ docker run -p 9001:8080 ... \
                 --env eureka.instance.hostname=yy.yy.yy.yy \
                 --env eureka.instance.nonSecurePort=9001
    

    Be sure to set yy.yy.yy.yy to your VM's IP address.