Rest Template Exchange not working inside docker container but working outside

Viewed 1008

I have the following java code:

  ResponseEntity<FAQResolver.FAQResponse[]> responseEntity = restTemplate.exchange(SUGGESTION_URL, HttpMethod.POST,
                    requestEntity, FAQResolver.FAQResponse[].class);

Now if I try to run the java application inside docker through docker-compose, I get

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8888/search": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
searchbot_1      |
searchbot_1      | org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8888/search": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
searchbot_1      |      at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:744)
searchbot_1      |      at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
searchbot_1      |      at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579)
searchbot_1      |      at com.globant.fluentlab.searchbot.search.api.SearchController.suggest(SearchController.java:106)
searchbot_1      |      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
searchbot_1      |      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
searchbot_1      |      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
searchbot_1      |      at java.lang.reflect.Method.invoke(Method.java:498)
searchbot_1      |      at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
searchbot_1      |      at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
searchbot_1      |      at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
searchbot_1      |      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
searchbot_1      |      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
searchbot_1      |      at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
searchbot_1      |      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
searchbot_1      |      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
searchbot_1      |      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
searchbot_1      |      at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
searchbot_1      |      at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
searchbot_1      |      at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
searchbot_1      |      at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
searchbot_1      |      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
searchbot_1      |      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
searchbot_1      |      at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
searchbot_1      |      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
searchbot_1      |      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
searchbot_1      |      at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
searchbot_1      |      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
searchbot_1      |      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)

However if I stop the java application running in docker an use Intellij's debu g mode I get: Same code works locally without docker

To be quite honest I don't know why. I was wondering if docker-compose is restricting communication between containers or something. Any help will be much appreciated.

4 Answers
I/O error on POST request for "http://localhost:8888/search": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)

This means that restTemplate can not reach SUGGESTION_URL

Is SUGGESTION_URL already available under an other service?

If yes then are both of those services (your spring boot app and SUGGESTION_URL) defined in the same docker-compose as services? If they are under the same docker-compose then they shouldn't have any problem communicating. In that case I would check the SUGGESTION_URL to be sure it is correct , port numb , ip ...etc

Well, my boss just came back from holidays and answered this. Basically when you have several services running using docker-compose they can't find each other using localhost. Instead you must use the name of the service you want to connect to. This means SUGGESTION_URL = http://faqserver:8888/search. That did the trick for me. Hope this helps anyone if they get stuck like me.

this happens due to the fact that you are using localhost to reach out the service. I provide you an example below:

version: '3.7'

services:

  currency-exchange:
    image: chaklader/mmv2-currency-exchange-service:0.0.1-SNAPSHOT
    mem_limit: 700m
    ports:
      - "8000:8000"
    networks:
      - currency-network  
    depends_on:
      - naming-server 
    environment:
      EUREKA.CLIENT.SERVICEURL.DEFAULTZONE: http://naming-server:8761/eureka  
  
  naming-server:
    image: chaklader/mmv2-naming-server:0.0.1-SNAPSHOT
    mem_limit: 700m
    ports:
      - "8761:8761"
    networks:
      - currency-network  

If you are running locally, the Eureka will be available in localhost, but, in the container environments, you will need to reference like below:

http://naming-server:8761/eureka

Or you can reference the localhost of the machine, which runs the docker-compose by using host.docker.internal instead.

So your restTemplate call would look like this instead:

restTemplate.exchange(
        SUGGESTION_URL.replace("localhost", "host.docker.internal"), 
        HttpMethod.POST,
        requestEntity,
        FAQResolver.FAQResponse[].class);
Related