5

I have two SpringBoot microservices M1(port 2002) and M2(port 2004)

M1 and M2 are communicating successfully if I run them using eclipse (run as Java Project or SpringBoot Project).

However, I want to communicate them using Docker container.

So I build images for both Microservices (M1 and M2) using the command:

docker build -f Dockerfile -t image_name .

And run the images using:

docker run -p 2004:2004 image_name

Note: I am exposing same port from docker as defined above

But the M1 and M2 are not able to communicate. I am using RestTemplate

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> isUp = restTemplate.getForEntity("http://localhost:2002/apis/test",Boolean.class);

I am getting below exception :

I/O error on GET request for \"http://localhost:2002/apis/test\": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)

However, If I call the other microservice using my machine's IP, It's communicating successfully

ResponseEntity<Boolean> isUp = restTemplate.getForEntity("http://XX.XX.XX.XXX:2002/apis/test",Boolean.class);

Can someone please tell if I am doing it write(using IP address) or there is another good approach to call one microservice from another using Docker?

Mehraj Malik
  • 14,872
  • 15
  • 58
  • 85
  • Have you tried using `--net=host` (parameter for docker run)? This should fix the issue that localhost refers the internal ip of the container and not the machines ip. – Ben Jul 19 '18 at 07:18
  • @Ben no, could you please add it as an answer. And what I replace `host` with? – Mehraj Malik Jul 19 '18 at 07:19
  • As it's more a suggestion not a straight up answer a comment is just fine here. Also are you sure that doesn't help? Because localhost should 100% reference the host machine in that moment. Reference [this](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach) question, the accepted answer goes into great detail explaining things. – Ben Jul 19 '18 at 07:20
  • Even though the answer from Ben will probably work, it might not be the best thing to do. You should read the doc first https://docs.docker.com/network/ – StephaneM Jul 19 '18 at 07:23
  • http://javaonfly.blogspot.com/2017/07/microservices-communication-feign-as.html, try this – Jinna Balu Jul 19 '18 at 07:30
  • @JinnaBalu The question is about how to `Using docker`, I know I can use Feign replacing RestTemplate. But this does not resolve the problem using `Docker container` – Mehraj Malik Jul 19 '18 at 07:32
  • Are those containers are in the same network? If so they will communicate with Feign Rest Client. Evn if they are not in the same network if the Ips and ports are opened between the netwrk it will work. – Jinna Balu Jul 19 '18 at 07:36
  • You may also be interested in Docker Compose : https://docs.docker.com/compose/ – Arnaud Jul 19 '18 at 08:36

2 Answers2

6

Trying to communicate with the other container won't work with localhost.

You should create a custom bridged network, which will allow you to refer to the containers by name. And there is no need to publish the ports if you are only talking internally.

# create network
docker network create -d bridge mynet
# container 1
docker container run --network mynet --name container1 -d image_name
# container 2
docker container run --network mynet --name container2 -d some_other_image_name

The IP in code snippet can then be replaced with the name of the other container

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> isUp = restTemplate.getForEntity("http://container2:2002/apis/test",Boolean.class)
chris
  • 4,332
  • 5
  • 41
  • 61
3

Alternately, you can also link the two containers together by --link. Assuming you want container1 as client to container2, you can use below:

sudo docker run --link container2 --name=container1 -d image_name
piy26
  • 1,574
  • 11
  • 21