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!
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 oflocalhost
, you have to address the server with a chosen alias, sayserver
. Once you've edited the client code and rebuiltclientimage
, try the following:sudo docker network create client_server_network
sudo docker run --network-alias server --network client_server_network -it serverimage
sudo docker run --network client_server_network -it clientimage
message= Hello Server
print in the server terminalNote that I provided an additional
--network-alias server
to the server'sdocker 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 todocker run
. You'll need some of the same updates as above, notably using something likeserver
in place oflocalhost
, and running the server container with--name server
. The docker run would look like:sudo docker run --name server -it serverimage
sudo docker run --link server -it clientimage
message= Hello Server
print in the server terminalThere are 3 problems:
Also, there's no need for the EXPOSE directive in the client Dockerfile.