gpt4 book ai didi

docker - Java 应用程序无法使用静态 IP 获取 docker 容器中主机的 IP 地址

转载 作者:行者123 更新时间:2023-12-02 18:44:23 27 4
gpt4 key购买 nike

我有一段时间使用 OpenStack 来管理我的应用程序。现在我想将它们作为每个应用程序的容器转移到 docker,因为 docker 更轻量级和高效。

问题是几乎所有与网络相关的事情在运行时都出错了。

在我的设计中,每个应用程序容器都应该有一个静态 IP 地址,我可以使用 hosts 文件来定位容器网络。

这是我的实现。 (bash 文件名是 docker_addnet.sh)

# Useages
# docker_addnet.sh container_name IP
# interface name: veth_(containername)
# gateway 172.17.42.1

if [ $# != 2 ]; then
echo -e "ERROR! Wrong args"
exit 1
fi

container_netmask=16
container_gw=172.17.42.1

container_name=$1
bridge_if=veth_`echo ${container_name} | cut -c 1-10`
container_ip=$2/${container_netmask}
container_id=`docker ps | grep $1 | awk '{print \$1}'`
pid=`docker inspect -f '{{.State.Pid}}' ${container_name}`

echo "Contaner: " $container_name "pid: " $pid

mkdir -p /var/run/netns
ln -s /proc/$pid/ns/net /var/run/netns/$pid

brctl delif docker0 $bridge_if

ip link add A type veth peer name B
ip link set A name $bridge_if
brctl addif docker0 $bridge_if
ip link set $bridge_if up
ip link set B netns $pid
ip netns exec $pid ip link set dev B name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $container_ip dev eth0
ip netns exec $pid ip route add default via $container_gw

该脚本用于设置容器的静态IP地址,然后运行容器,必须附加 --net=none手动设置网络

您现在可以通过以下方式启动容器
sudo docker run --rm -it --name repl --dns=8.8.8.8 --net=none clojure bash

并设置网络
sudo zsh docker_addnet.sh repl 172.17.15.1

在容器 bash 中,可以通过 ip addr 看到 IP 地址,输出类似于
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
67: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 2e:7b:7e:5a:b5:d6 brd ff:ff:ff:ff:ff:ff
inet 172.17.15.1/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::2c7b:7eff:fe5a:b5d6/64 scope link
valid_lft forever preferred_lft forever

到现在为止还挺好。

让我们尝试使用 clojure repl 获取容器主机 ip 地址。首先是repl:
lein repl

接下来评估下面的代码
(. java.net.InetAddress getLocalHost)

clojure 代码等于
System.out.println(Inet4Address.getLocalHost());

你得到的是一个异常(exception)

UnknownHostException 5a8efbf89c79: Name or service not known java.net.Inet6AddressImpl.lookupAllHostAddr (Inet6AddressImpl.java:-2)



其他奇怪的事情是 RMI 服务器无法通过 RemoteServer.getClientHost(); 获取客户端 IP 地址。 .

那么什么可能导致这个问题呢?我记得java有时会得到错误的网络配置,但我不知道原因。

最佳答案

documentation对于 InetAddress.getLocalHost()说:

Returns the address of the local host. This is achieved by retrieving the name of the host from the system, then resolving that name into an InetAddress.



由于您没有采取任何步骤使您的静态 IP 地址在容器内可解析,因此它不起作用。

要在不通过主机名的情况下在 Java 中查找地址,您可以通过 NetworkInterface.getNetworkInterfaces() 枚举所有网络接口(interface),然后遍历每个接口(interface),检查每个地址以找到您想要的。示例代码在
Getting the IP address of the current machine using Java

另一种选择是使用 Docker 的 --add-host--hostname docker run 上的选项命令输入你想要的地址的映射,然后 getLocalHost()应该按您的预期工作。

关于docker - Java 应用程序无法使用静态 IP 获取 docker 容器中主机的 IP 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27087786/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com