linux - 如何配置 Docker 以使用我的 ens34 网络接口(interface)(而不是 eth0)?

标签 linux networking docker routes iptables

有谁知道 docker 如何决定哪个 NIC 将与 docker0 网络一起工作?我有一个具有两个接口(interface)(eth0 和 ens34)的节点,但是,只有通过 eth0 的请求才会转发到容器。

当我的虚拟机配置好并安装了 Docker 后,我开始了一个非常愚蠢的测试:我创建了一个 centos 虚拟机,在上面安装了 netcat 并提交了图像。然后我启动了一个监听端口 8080 的守护进程容器。我使用了:

docker -it -p 8080:8080 --name nc-server nc-server nc -vv -l 8080

所以我尝试从同一网络中的另一个节点连接到监听端口 8080 的容器(与接口(interface) ens34 具有相同的 IP 地址)。它没有用。

而当我从另一台机器向 eth0 的 IP 地址发送请求时,我在容器中看到了一些 react (通信正常)。我正在“拖尾”它的输出:

docker logs -ft nc-server

我对这个实验的结论:eth0(主网卡)和 docker0 之间存在某种神秘的关系,发送到 ens34(10.)接口(interface)的请求永远不会转发到 veth/docker0接口(interface),只有通过 eth0 (9.*) 的请求。这是为什么?

此外,我知道如果我使用 --net=host 我可以让一切正常工作,但我不想使用它...不知何故感觉不对,使用 HOST 是标准做法吗Docker容器中的模式?有什么注意事项吗?

--

更新: 我在禁用 iptables 后设法让它工作:

service iptables stop

但是,我还是不明白发生了什么。以下信息应该与了解正在发生的事情相关:

配置文件

[root@mydockervm2 myuser]# ifconfig | grep -A 1 flags
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
--
ens34: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.1.21.18  netmask 255.255.255.0  broadcast 10.1.21.255
--
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 9.32.145.99  netmask 255.255.255.0  broadcast 9.32.148.255
--
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
--
veth8dbab2f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::3815:67ff:fe9b:88e9  prefixlen 64  scopeid 0x20<link>
--
virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255

网络统计

[root@mydockervm2 myuser]# netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         9.32.145.1      0.0.0.0         UG        0 0          0 eth0
9.32.145.0      0.0.0.0         255.255.255.0   U         0 0          0 eth0
10.1.21.0       0.0.0.0         255.255.255.0   U         0 0          0 ens34
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 ens34
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 docker0
192.168.122.0   0.0.0.0         255.255.255.0   U         0 0          0 virbr0

过滤器

[root@mydockervm2 myuser]# iptables -t filter -vS
-P INPUT ACCEPT -c 169 106311
-P FORWARD ACCEPT -c 0 0
-P OUTPUT ACCEPT -c 110 13426
-N DOCKER
-N DOCKER-ISOLATION
-A FORWARD -c 0 0 -j DOCKER-ISOLATION
-A FORWARD -o docker0 -c 0 0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -c 0 0 -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -c 0 0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -c 0 0 -j ACCEPT
-A FORWARD -m physdev --physdev-is-bridged -c 0 0 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -c 0 0 -j ACCEPT
-A DOCKER-ISOLATION -c 0 0 -j RETURN

自然

[root@mydockervm2 myuser]# iptables -t nat -vS
-P PREROUTING ACCEPT -c 28 4818
-P INPUT ACCEPT -c 28 4818
-P OUTPUT ACCEPT -c 8 572
-P POSTROUTING ACCEPT -c 8 572
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -c 2 98 -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -c 0 0 -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -c 0 0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8080 -c 0 0 -j MASQUERADE
-A DOCKER -i docker0 -c 0 0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -c 0 0 -j DNAT --to-destination 172.17.0.2:8080

想法?

最佳答案

首先,排除显而易见的问题并确保其他网络上的主机知道如何路由到您的机器以到达容器网络。为此,检查

netstat -nr

在源主机上并确保您的 docker 子网以您的 docker 主机作为网关列出,或者处理上游流量的默认路由器知道您的主机。

如果流量被路由但被阻止,那么您将进入转发和 iptables 。对于转发,以下应显示 1:

cat /proc/sys/net/ipv4/ip_forward

确保您的本地主机使用相同的 netstat 命令显示通往您的容器网络的网桥路由,应该有一行表示 docker0 接口(interface)和您的 docker 子网作为目的地:

netstat -nr

对于iptables,查看是否有接口(interface)特定的nat或者filter规则需要调整:

iptables -t filter -vS
iptables -t nat -vS

如果您的转发规则默认为 DROP 而不是 ACCEPT,您可能需要添加一些日志记录,或者如果您认为流量是可信的(例如,主机在另一个防火墙后面),则只需更改默认以接受流量。

综上所述,直接在主机上公布端口是容器的一种相当普遍的做法。对于私有(private)的东西,您可以在其内部网络上设置多个容器,这些容器可以相互通信,但不能与其他容器通信,并且您只使用 -p 标志在主机上公开真正向世界其他地方开放的端口运行(或 docker-compose 中的端口选项)。

关于linux - 如何配置 Docker 以使用我的 ens34 网络接口(interface)(而不是 eth0)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37757759/

相关文章:

php - 在 Joomla 中获取文件内容

mysql - 在我自己的桌面上使用 virtualbox LAMP

c - 服务器程序卡在 read() 函数上,但 write() 函数在客户端程序中运行良好

security - WebSocket:客户端如何获取服务器 guid?

python - 在大文本文件中查找重复记录

java - 从java代码中查找连接到android热点的ip地址

java - 如何测量单向延迟?

docker - Dockerfile在Linux容器上安装.NET软件包?

docker - 使用 sysctl 更改 docker 文件中的内核参数,运行的容器是否会影响主机内核

docker - SEO URL 在带有 Docker 的 OpenCart 2.3 中给出 404 错误