проблема с подключение клиента к серверу (Java Socket) после контейнеризации Docker

Сервер прослушивает клиентов на порту 80, клиент так же подключается к этому порту.
Дальше я создаю два различных образа. Один для сервера, второй для клиента.
В папке где у меня лежит сервер я имею следуюющий Dockerfile:

FROM openjdk
COPY . /java
WORKDIR /java
EXPOSE 80
RUN javac API.java
CMD ["java", "API"]

В папке с клиентом Dockerfile написан так:

FROM openjdk
COPY . /java
WORKDIR /java
EXPOSE 80
RUN javac CLI.java
CMD ["java", "CLI"]

Дальше я создаю образы с помощью docker build . в каждой папке, и в итоге получаю два образа, один для сервера, второй для клиента.
Следующим шагом я запускаю сервер так:

docker run -p 8001:80 id_api_image

И у меня сервер запущен, все работает.
Дальше я пытаюсь запустить клиента:

docker run -p 8002:80 id_cli_image

И здесь я получаю ошибку:

java.net.ConnectException: Connection refused
at java.base/sun.nio.ch.Net.connect0(Native Method)
at java.base/sun.nio.ch.Net.connect(Net.java:579)
at java.base/sun.nio.ch.Net.connect(Net.java:568)
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:585)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
at java.base/java.net.Socket.connect(Socket.java:633)
at java.base/java.net.Socket.connect(Socket.java:583)
at java.base/java.net.Socket.(Socket.java:507)
at java.base/java.net.Socket.(Socket.java:287)
at CLI.main(CLI.java:9)

Возможно это происходит через то что сервер вообще находится в другом контейнере, поэтому клиент и не может его найти, не знаю. Если и так, тогда как мне решить мою проблему?


Ответы (1 шт):

Автор решения: KoVadim

Так как все теперь в докере, то серверный порт поменялся. Если можете запустить сервер вот так docker run -p 80:80 id_api_image, а вот клиента так docker run id_cli_image - клиенту не нужно открывать порт, значит и не нужно наружу показывать порт. Все должно заработать.

Если же запускаете сервер вот так docker run -p 8001:80 id_api_image, то в клиенте в коде нужно поправить порт, на который все будет подключаться. Код клиента нужно будет поправить.

И есть ещё третий вариант - это сделать docker-compose файл или всех добавить в одну сеть вручную.

Если через докер напрямую, то вначале нужно создать сеть https://docs.docker.com/engine/reference/commandline/network_create/

docker network create -d bridge my-bridge-network

(my-bridge-network - это имя созданной сети)

А потом подсказать докеру, что для контейнера нужно использовать эту сеть --network=my-bridge-network.

И получается так, сервер:

docker run -p 8001:80 --network=my-bridge-network id_api_image

клиент

docker run --network=my-bridge-network id_cli_image

В этом случае порты менять не нужно, а для сервера даже можно удалить -p 8001:80, если сервер не будет использоваться за пределами этих двух контейнеров.

Это работает, так как мы вручную указали, что клиент и сервер находятся в одной сети. Правда тут есть одна проблема - это адрес (ip) подключения (адрес самого сервера). Так как теперь у нас это все находится внутри отдельной сети, то и адреса там другие. Я сделал через docker inspect <id контейнера сервера> и просто посмотрел его адрес (в виде ip) либо в docker container ps посмотреть id сервера (оно выглядит как 99a38de850af) и использовать его в качестве адреса хоста (хотя у меня есть подозрение, что некоторые приложения будут против)

Если же используете docker-compose, то там это можно сделать автоматически, а имя "сервера" задать самому.

→ Ссылка