I am learning Docker now. And i have faced with a problem: I have been practiced Docker Compose and got a problem with creating containers. The task: There is a Server (Java). The server is very simple. It is just waiting messages from clients and printing them. There are not any threads or something like that. It is not what this app about. The code of the server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
class Server {
public static void main(String[] args) throws IOException {
System.out.println("Server was started!");
try (ServerSocket serverSocket = new ServerSocket(8899)) {
while (true) {
try (Socket client = serverSocket.accept()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = reader.readLine();
System.out.println(client.getInetAddress().getHostAddress() " - " line);
} catch (Exception e) {
System.out.println("Dops");
}
}
}
}
}
There are two clients. Also Java language. They are also very simple:
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
class Client {
public static void main(String[] args) throws IOException, InterruptedException {
String ip = "app_server";
while (true){
try (Socket socket = new Socket(ip, 8899)) {
System.out.println("An attempt...");
Thread.sleep(10000);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String message = "Hello from client_1\n";
writer.write(message);
writer.flush();
System.out.println("The package was sent!");
}
}
}
}
The second client is totaly the same, but the message is "Hello from client_2\n".
So the idea is to create 3 containers (Server, Client#1, Client#2). And clients have to send a message to the server every 10 seconds. I have tried that on my computer and everithing was fine. It worked perfectly. But I used definite IP 192.168.7.121 in Client app code.
So I created folders:
Dockerfile from Client 1:
FROM openjdk:11
WORKDIR /app_client1
COPY . .
RUN javac Client.java
CMD [ "java", "Client" ]
Dockerfile from Client 2:
FROM openjdk:11
WORKDIR /app_client2
COPY . .
RUN javac Client.java
CMD [ "java", "Client" ]
Docker file from Server
FROM openjdk:11
WORKDIR /app_server
COPY . .
RUN javac Server.java
CMD [ "java", "Server" ]
docker-compose:
version: '3'
services:
app_server:
build: ./app_server
app_client1:
build: ./app_client1
app_client2:
build: ./app_client2
And after i had typed the comand "docker-compose up" to terminal, a got this:
PS D:\it\dockerNet\docker-compose-app> docker-compose up
[ ] Running 3/3
- Container docker-compose-app-app_server-1 Cr... 0.6s
- Container docker-compose-app-app_client2-1 C... 0.6s
- Container docker-compose-app-app_client1-1 C... 0.6s
Attaching to docker-compose-app-app_client1-1, docker-compose-app-app_client2-1, docker-compose-app-app_server-1
docker-compose-app-app_client1-1 | Exception in thread "main" java.net.ConnectException: Connection refused (Connection refused)
docker-compose-app-app_client1-1 | at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
docker-compose-app-app_client1-1 | at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
docker-compose-app-app_client1-1 | at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
docker-compose-app-app_client1-1 | at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
docker-compose-app-app_client1-1 | at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.connect(Socket.java:609)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.connect(Socket.java:558)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.<init>(Socket.java:454)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.<init>(Socket.java:231)
docker-compose-app-app_client1-1 | at Client.main(Client.java:15)
docker-compose-app-app_server-1 | /bin/sh: 1: [java,: not found
docker-compose-app-app_client1-1 exited with code 1
docker-compose-app-app_server-1 exited with code 127
docker-compose-app-app_client2-1 | Exception in thread "main" java.net.NoRouteToHostException: No route to host (Host unreachable)
docker-compose-app-app_client2-1 | at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
docker-compose-app-app_client2-1 | at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
docker-compose-app-app_client2-1 | at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
docker-compose-app-app_client2-1 | at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
docker-compose-app-app_client2-1 | at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.connect(Socket.java:609)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.connect(Socket.java:558)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.<init>(Socket.java:454)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.<init>(Socket.java:231)
docker-compose-app-app_client2-1 | at Client.main(Client.java:15)
docker-compose-app-app_client2-1 exited with code 1
And now there are two questions:
Can I change Server IP address by the service name "app_server". Regarding youtube tutorials it is probably possible. If I can`t use that How I suposse to know IP address of the Server before containers creating?
I do not understand why i can not create containers. Where is mistake and what is wrong? What I have done wrong?
I will be very gratefull for you help!
update:
According to advice in comments bellow, I changed code in both Clients to avoid possible exceptions. Now they look like:
import java.io.IOException;
class Client {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("TEST");
}
}
But I still have error:
PS D:\it\dockerNet\docker-compose-app> docker-compose up
[ ] Running 3/0
- Container docker-compose-app-app_client2-1 C... 0.0s
- Container docker-compose-app-app_server-1 Cr... 0.0s
- Container docker-compose-app-app_client1-1 C... 0.0s
Attaching to docker-compose-app-app_client1-1, docker-compose-app-app_client2-1, docker-compose-app-app_server-1
docker-compose-app-app_server-1 | /bin/sh: 1: [java,: not found
docker-compose-app-app_server-1 exited with code 127
docker-compose-app-app_client2-1 | Exception in thread "main" java.net.NoRouteToHostException: No route to host (Host unreachable)
docker-compose-app-app_client1-1 | Exception in thread "main" java.net.NoRouteToHostException: No route to host (Host unreachable)
docker-compose-app-app_client2-1 | at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
docker-compose-app-app_client1-1 | at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
docker-compose-app-app_client2-1 | at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
docker-compose-app-app_client1-1 | at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
docker-compose-app-app_client2-1 | at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
docker-compose-app-app_client1-1 | at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
docker-compose-app-app_client2-1 | at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
docker-compose-app-app_client1-1 | at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
docker-compose-app-app_client2-1 | at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
docker-compose-app-app_client1-1 | at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.connect(Socket.java:609)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.connect(Socket.java:609)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.connect(Socket.java:558)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.connect(Socket.java:558)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.<init>(Socket.java:454)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.<init>(Socket.java:454)
docker-compose-app-app_client2-1 | at java.base/java.net.Socket.<init>(Socket.java:231)
docker-compose-app-app_client1-1 | at java.base/java.net.Socket.<init>(Socket.java:231)
docker-compose-app-app_client2-1 | at Client.main(Client.java:15)
docker-compose-app-app_client1-1 | at Client.main(Client.java:15)
docker-compose-app-app_client1-1 exited with code 1
docker-compose-app-app_client2-1 exited with code 1
CodePudding user response:
SERVER - MYSERVER.java
package org.example;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MYSERVER {
public static void main(String[] args) {
System.out.println("Hello world!");
System.out.println("Server was started!");
try (ServerSocket serverSocket = new ServerSocket(8899)) {
while (true) {
try (Socket client = serverSocket.accept()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = reader.readLine();
System.out.println(client.getInetAddress().getHostAddress() " - " line);
} catch (Exception e) {
System.out.println("Dops");
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
CLIENT - MYCLIENT.java
package org.example;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Calendar;
public class MYCLIENT {
public static void main(String[] args) {
System.out.println("Hello world!");
String ip = "localhost";
if (args.length > 0) ip= args[0];
System.out.println("ip=" MYCLIENT.javaip);
int no = 1;
if (args.length > 1) no= Integer.parseInt(args[1]);
String whoami="client #" no;
System.out.println("whoami=" whoami);
while (true){
try (Socket socket = new Socket(ip, 8899)) {
System.out.println("An attempt...");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String message = "Hello from " whoami " at " Calendar.getInstance().getTime() "\n";
writer.write(message);
writer.flush();
System.out.println("The package was sent!");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(10000);
}catch (InterruptedException e) {
//do nothing
}
}
}
}
BUILD JAVA TO EXECUTE JAR
- MYCLIENT-1.0-SNAPSHOT.jar
- MYSERVER-1.0-SNAPSHOT.jar
HOST TEST
- Open Terminal 1:
java -jar MYSERVER-1.0-SNAPSHOT.jar
- Open Terminal 2:
java -jar MYCLIENT-1.0-SNAPSHOT.jar localhost 1
- Open Terminal 3:
java -jar MYCLIENT-1.0-SNAPSHOT.jar localhost 2
- Open Terminal 4:
java -jar MYCLIENT-1.0-SNAPSHOT.jar localhost 3
MY_SERVER_CLIENT
├── docker-compose.yml
├── MYCLIENT
│ ├── Dockerfile
│ └── MYCLIENT-1.0-SNAPSHOT.jar
└── MYSERVER
├── Dockerfile
└── MYSERVER-1.0-SNAPSHOT.jar
MYSERVER - Dockerfile
FROM eclipse-temurin:17.0.5_8-jre-ubi9-minimal
EXPOSE 8899
WORKDIR /app
COPY MYSERVER-1.0-SNAPSHOT.jar /app/app.jar
ENTRYPOINT ["java","-jar", "app.jar"]
MYSERVER - build command
docker build -t demoserver:1.0.0 .
docker tag demoserver:1.0.0 demoserver:latest
MYCLIENT - Dockerfile
FROM eclipse-temurin:17.0.5_8-jre-ubi9-minimal
WORKDIR /app
COPY MYCLIENT-1.0-SNAPSHOT.jar /app/app.jar
ENTRYPOINT ["java","-jar", "app.jar"]
CMD ["locahost","1"]
MYCLIENT - build command
docker build -t democlient:1.0.0 .
docker tag democlient:1.0.0 democlient:latest
TEST
Test Server - demoserver
- Open terminal 1:
docker run -it demoserver
- Open terminal 2:
docker ps
- terminal 2:
docker inspect demoserver-container-id
Get container ip like "IPAddress": "172.17.0.2"
Test Client - client
- Open terminal 3:
docker run -it democlient 172.17.0.2 1
- Open terminal 4:
docker run -it democlient 172.17.0.2 2
- Open terminal 5:
docker run -it democlient 172.17.0.2 3
- Open terminal 6:
docker run -it democlient 172.17.0.2 4
See Terminal 1
FIND
$ docker run -it demoserver
Hello world!
Server was started!
172.17.0.3 - Hello from client #1 at Sun Dec 11 10:07:47 GMT 2022
172.17.0.3 - Hello from client #1 at Sun Dec 11 10:07:57 GMT 2022
172.17.0.4 - Hello from client #2 at Sun Dec 11 10:08:02 GMT 2022
172.17.0.3 - Hello from client #1 at Sun Dec 11 10:08:07 GMT 2022
172.17.0.4 - Hello from client #2 at Sun Dec 11 10:08:12 GMT 2022
172.17.0.3 - Hello from client #1 at Sun Dec 11 10:08:17 GMT 2022
172.17.0.5 - Hello from client #3 at Sun Dec 11 10:08:17 GMT 2022
172.17.0.4 - Hello from client #2 at Sun Dec 11 10:08:22 GMT 2022
Last Step Create docker-compose.yml
docker-compose.yml
version: '3.4'
services:
demoserver:
image: demoserver
democlient1:
image: democlient
command: demoserver 1
depends_on:
- demoserver
democlient2:
image: democlient
command: demoserver 2
depends_on:
- demoserver
democlient3:
image: democlient
command: demoserver 3
depends_on:
- demoserver
Run docker compose
Open terminal:
docker compose up
$ docker compose up [ ] Running 4/0 ⠿ Container my_server_client-demoserver-1 Created 0.0s ⠿ Container my_server_client-democlient3-1 Created 0.0s ⠿ Container my_server_client-democlient1-1 Created 0.0s ⠿ Container my_server_client-democlient2-1 Created 0.0s Attaching to my_server_client-democlient1-1, my_server_client-democlient2-1, my_server_client-democlient3-1, my_server_client-demoserver-1 my_server_client-demoserver-1 | Hello world! my_server_client-demoserver-1 | Server was started! my_server_client-democlient2-1 | Hello world! my_server_client-democlient2-1 | ip=demoserver my_server_client-democlient2-1 | whoami=client #2 my_server_client-democlient2-1 | An attempt... my_server_client-democlient3-1 | Hello world! my_server_client-democlient3-1 | ip=demoserver my_server_client-democlient1-1 | Hello world! my_server_client-democlient3-1 | whoami=client #3 my_server_client-democlient2-1 | The package was sent! my_server_client-democlient1-1 | ip=demoserver my_server_client-demoserver-1 | 172.18.0.3 - Hello from client #2 at Sun Dec 11 10:29:55 GMT 2022 my_server_client-democlient1-1 | whoami=client #1 my_server_client-democlient3-1 | An attempt... my_server_client-democlient1-1 | An attempt... my_server_client-democlient3-1 | The package was sent! my_server_client-demoserver-1 | 172.18.0.4 - Hello from client #3 at Sun Dec 11 10:29:55 GMT 2022 my_server_client-democlient1-1 | The package was sent! my_server_client-demoserver-1 | 172.18.0.5 - Hello from client #1 at Sun Dec 11 10:29:55 GMT 2022
Run docker compose again
- Open terminal:
docker compose up --scale app_client1=10
DIY
services:
demoserver:
image: demoserver
democlient1:
image: democlient
...
Change image
to build
yourself.
Do one thing at a time
- Step 1. test java part, server , client
- Step 2. package server, client as execute jar
- Step 3. test it on host, not on docker
- Step 4. pack server to docker image
- Step 5. test server use docker image, but test client on host
- Step 6. pack client to docker image
- Step 7. test server image and client image
- Step 8. build
docker-compose.yml
- Step 9. test docker compose
I am used to cutting the problem into many parts, then solving each part, testing each part, and finally combining each part But each part has been tested, so I can know what the message is if an error occurs, which part is wrong, and how to deal with it.