Docker communication between two containers with J

2019-05-22 15:12发布

问题:

There are two java files, Server.java and Client.java. Both are in separate containers.

DOCKER FILES: The dockerfile(in the folder named 'Server') that i use for server is:

FROM java:8
COPY Server.java /
RUN javac Server.java
EXPOSE 25000
ENTRYPOINT ["java"]
CMD ["Server"]

The dockerfile(in the folder named 'Client') for client is:

FROM java:8
COPY Client.java /
RUN javac Client.java
EXPOSE 25000
ENTRYPOINT ["java"]
CMD ["Client"]

BUILDING THE CONTAINERS: Building the containers using sudo docker build -t serverimage .

RUNNING THE CONTAINERS: I run the images using the command sudo docker run <IMAGE_NAME>.And I am running the serverimage first.

The error i am getting(When i run clientimage) is:

java.net.ConnectException: Connection refused: connect

Server.java File:

import java.io.*;  
import java.net.*;  
public class MyServer {  
   public static void main(String[] args){  
       try{  
           ServerSocket ss=new ServerSocket(25000);  
           Socket s=ss.accept();//establishes connection   
           DataInputStream dis=new DataInputStream(s.getInputStream());  
           String  str=(String)dis.readUTF();  
           System.out.println("message= "+str);  
           ss.close();  
       }catch(Exception e){System.out.println(e);}  
   }  
}  

Client.java File:

import java.io.*;  
import java.net.*;  
public class MyClient {  
   public static void main(String[] args) {  
      try{      
         Socket s=new Socket("localhost",25000);  
         DataOutputStream dout=new DataOutputStream(s.getOutputStream());  
         dout.writeUTF("Hello Server");  
         dout.flush();  
         dout.close();  
         s.close();  
      }catch(Exception e){System.out.println(e);}  
   }  
}  

What am I possibly doing wrong? Thank you!

回答1:

For modern docker versions (1.13+)

To understand where this approach goes wrong, the docker networking guide has all of the intricate details, but it largely boils down to the fact that you can't simply reference localhost in one container and expect it to route to another container running on your host.

By default each container runs on a bridge network, and each container effectively appears as a separate host on that bridge network, in the same subnet. The containers can reference other containers via their assigned IP address on the bridge network, but localhost simply refers to the container itself, rather than the underlying host that's running the container.

To achieve predictable routing similar to what you're after, you can define your own bridge network and run the client and server containers on that user-defined network. This does require one small code change in your Client.java. Instead of localhost, you have to address the server with a chosen alias, say server. Once you've edited the client code and rebuilt clientimage, try the following:

  • Create the network - sudo docker network create client_server_network
  • Run the server - sudo docker run --network-alias server --network client_server_network -it serverimage
  • Run the client - sudo docker run --network client_server_network -it clientimage
  • You should see message= Hello Server print in the server terminal

Note that I provided an additional --network-alias server to the server's docker run, to add a network alias where the client can predictably reach the server container. You have multiple ways of achieving that aliasing, including using the --name option, but check out the docker embedded dns docs for more details.

For older docker versions (1.12-)

Docker provides a container linking functionality, exposed via the --link option supplied to docker run. You'll need some of the same updates as above, notably using something like server in place of localhost, and running the server container with --name server. The docker run would look like:

  • Run the server - sudo docker run --name server -it serverimage
  • Run the client - sudo docker run --link server -it clientimage
  • You should see message= Hello Server print in the server terminal


回答2:

There are 3 problems:

  1. The classes should be named Server and Client, or else the Server.java & Client.Java files should be named MyServer.java & MyClient.java, respectively.
  2. When you create a Docker container, 2 interfaces are created: localhost and another interface for communicating with other containers. You should change "localhost" to the server container IP or the host IP.
  3. The java images are deprecated.

Also, there's no need for the EXPOSE directive in the client Dockerfile.



标签: docker