如何在Docker容器中访问主机eno1网络(不使用--net=host)
我有一台多网卡主机:eth0是连接互联网的主接口,eno1是通过USB以太网适配器连接到私有交换机的接口,对应网段为172.16.0.0/22。
我需要在不使用--net=host参数(避免破坏容器网络隔离)的前提下,让Docker容器能访问该私有网段的设备(比如172.16.3.1:5555)。目前使用默认桥接网络启动容器时无法连接目标设备,但用--net=host可以正常连接。
环境信息
主机网络配置(ip -4 a输出)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 10.91.44.20/22 brd 10.91.47.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever 3: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 172.16.0.1/22 brd 172.16.3.255 scope global noprefixroute eno1 valid_lft forever preferred_lft forever 4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default inet 240.10.0.1/24 brd 240.10.0.255 scope global docker0 valid_lft forever preferred_lft forever
容器网络配置(默认桥接模式下ip -4 a输出)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 243: eth0@if244: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP inet 240.10.0.2/24 brd 240.10.0.255 scope global eth0 valid_lft forever preferred_lft forever
主机路由规则(ip route输出)
default via 10.91.44.1 dev eth0 proto static metric 20 default via 10.91.44.1 dev eno1 proto static metric 40 10.91.44.0/22 dev eth0 proto kernel scope link src 10.91.44.20 metric 20 10.91.44.1 dev eno1 proto static scope link metric 40 172.16.0.0/22 dev eno1 proto kernel scope link src 172.16.0.1 metric 40 240.10.0.0/24 dev docker0 proto kernel scope link src 240.10.0.1
以下几种方法都能在保持容器网络隔离的前提下,实现容器访问172.16.0.0/22网段:
方法1:给Docker添加静态路由并配置iptables转发
基于默认docker0桥接网络,无需修改容器启动参数,仅在主机上配置:
添加静态路由:让主机转发
docker0网段到私有网段的流量ip route add 172.16.0.0/22 via 172.16.0.1 dev eno1 src 240.10.0.1需永久生效可将命令添加到主机网络配置文件(如
/etc/rc.local)。配置iptables允许转发:
sudo iptables -A FORWARD -i docker0 -o eno1 -d 172.16.0.0/22 -j ACCEPT sudo iptables -A FORWARD -i eno1 -o docker0 -s 172.16.0.0/22 -j ACCEPT永久保存规则可执行
iptables-save > /etc/iptables/rules.v4(依系统调整)。
完成后用默认命令启动容器即可访问目标设备:
docker run -d --rm --init --name=test -i my-image:latest
方法2:创建自定义桥接网络并绑定到eno1
创建独立的Docker桥接网络,关联私有网段:
创建自定义桥接网络:
docker network create --driver bridge --subnet 240.10.1.0/24 --gateway 240.10.1.1 private-net添加路由规则:
ip route add 172.16.0.0/22 via 172.16.0.1 dev eno1 src 240.10.1.1配置iptables转发规则:
先通过docker network inspect private-net获取自定义网桥名称(如br-abc123),再执行:sudo iptables -A FORWARD -i br-<自定义网络ID> -o eno1 -d 172.16.0.0/22 -j ACCEPT sudo iptables -A FORWARD -i eno1 -o br-<自定义网络ID> -s 172.16.0.0/22 -j ACCEPT使用自定义网络启动容器:
docker run -d --rm --init --name=test --network private-net -i my-image:latest
方法3:使用Macvlan网络直接接入私有网段
让容器直接获取私有网段IP,相当于接入私有交换机网络:
创建Macvlan网络:
docker network create -d macvlan \ --subnet=172.16.0.0/22 \ --gateway=172.16.0.1 \ -o parent=eno1 \ macvlan-private使用Macvlan网络启动容器:
docker run -d --rm --init --name=test --network macvlan-private --ip 172.16.0.10 -i my-image:latest(
--ip可指定私有网段内未占用IP,也可省略让Docker自动分配)
此方法下容器直接成为私有网络的一部分,能直接访问目标设备,且保持与主机其他网络的隔离。
内容的提问来源于stack exchange,提问作者Vinayak

