проблема с подключение клиента к серверу (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 шт):
Так как все теперь в докере, то серверный порт поменялся. Если можете запустить сервер вот так 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, то там это можно сделать автоматически, а имя "сервера" задать самому.