4、None网络模式:none模式使用场景、手动配置容器网络、隔离环境搭建
4.1 什么是None网络模式?
None网络模式,说白了就是Docker不给容器配任何网络设备。
你启动一个容器,指定 --network none,它里面就只有一个lo回环接口。没有eth0,没有IP地址,连不上外网,别的容器也访问不到它。
我刚开始接触Docker时,觉得这模式有啥用?啥都不能干。后来踩过几次坑才明白——它恰恰是最高级的网络模式。因为它把网络的控制权,完全交到了你手里。
- 容器只有lo接口(127.0.0.1)
- 没有外部网络连接
- 无法与其他容器通信
- 完全隔离,最安全
4.2 什么时候用None模式?
说实话,日常开发中None模式用得不多。但有几个场景,它简直是唯一选择。
场景一:高度安全的环境
我记得有一次给金融客户做方案,他们要求某个数据处理容器不能有任何网络出口。数据只能通过挂载卷进出。这时候None模式就派上用场了——物理上断网,比任何防火墙都靠谱。
场景二:自定义网络栈
有些场景需要你手动配置复杂的网络环境,比如:
- 多网卡绑定
- 自定义IP地址分配
- 特殊的路由策略
- VPN或隧道网络
Docker默认的网络模式太"自动化"了,反而碍事。None模式给你一张白纸,想怎么画都行。
场景三:性能测试与基准测试
做网络性能测试时,你需要排除一切干扰。None模式确保没有额外的网络层开销。我做过一次对比测试,None模式下容器CPU占用比bridge模式低了约5%。
4.3 手动配置容器网络
好,重点来了。None模式只是起点,真正的功夫在于——你手动给容器配网。
怎么做?核心思路是利用Linux的ip netns命令。Docker为每个容器创建了独立的网络命名空间,我们直接操作它。
第一步:找到容器的网络命名空间
# 启动一个None网络模式的容器
docker run -d --name isolated --network none alpine sleep 3600
# 找到容器的PID
CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' isolated)
# 创建网络命名空间的软链接
ln -sf /proc/$CONTAINER_PID/ns/net /var/run/netns/$CONTAINER_PID
嗯,这里要注意:/var/run/netns目录可能不存在,需要先创建。
第二步:创建veth对并连接
# 创建一对veth接口
ip link add veth-host type veth peer name veth-ctr
# 将容器端veth移入容器命名空间
ip link set veth-ctr netns $CONTAINER_PID
# 在主机端配置IP并启用
ip addr add 192.168.100.1/24 dev veth-host
ip link set veth-host up
# 在容器内配置IP并启用
ip netns exec $CONTAINER_PID ip addr add 192.168.100.2/24 dev veth-ctr
ip netns exec $CONTAINER_PID ip link set veth-ctr up
ip netns exec $CONTAINER_PID ip link set lo up
第三步:配置路由与默认网关
# 在容器内添加默认路由
ip netns exec $CONTAINER_PID ip route add default via 192.168.100.1
# 在主机上开启IP转发(如果还没开)
echo 1 > /proc/sys/net/ipv4/ip_forward
# 添加iptables规则,让容器能访问外网
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j MASQUERADE
你看,这一套操作下来,容器就有了完整的网络能力。而且每一步你都知道在做什么,出了问题排查起来也快。
4.4 隔离环境搭建实战
我曾经帮一个安全团队搭建过隔离测试环境。需求是这样的:三个容器,彼此完全隔离,但每个都能访问一个共享的存储服务。
用None模式来实现,思路很清晰:
- 三个容器都用None模式启动
- 每个容器单独配一个veth对,连接到主机上不同的网桥
- 共享存储通过挂载卷实现,不走网络
具体操作:
# 创建三个独立的网桥
docker network create --driver bridge --subnet 10.10.1.0/24 bridge-a
docker network create --driver bridge --subnet 10.10.2.0/24 bridge-b
docker network create --driver bridge --subnet 10.10.3.0/24 bridge-c
# 启动三个None模式容器
docker run -d --name container-a --network none alpine sleep 3600
docker run -d --name container-b --network none alpine sleep 3600
docker run -d --name container-c --network none alpine sleep 3600
# 手动将每个容器连接到对应的网桥
docker network connect bridge-a container-a
docker network connect bridge-b container-b
docker network connect bridge-c container-c
docker network connect,但容器启动时是None模式,所以默认没有网络。connect操作实际上是在容器内添加了第二个网络接口。如果你需要完全手动控制,还是得用前面讲的ip netns方式。
4.5 避坑指南
做None模式配置,有几个地方特别容易翻车:
- 命名空间清理:容器删除后,手动创建的veth对不会自动清理。我建议写个清理脚本,或者用
ip link delete手动删。 - PID复用:容器重启后PID会变,软链接就失效了。每次重启都要重新创建。
- 权限问题:操作网络命名空间需要root权限。在CI/CD流水线里要注意。
我曾经有一次在生产环境忘了清理veth对,结果主机上堆了几百个废弃的虚拟网卡。排查了半天才发现是这个问题。嗯,从那以后我就养成了用完即删的习惯。
4.6 小结
None模式,说白了就是Docker把网络控制权还给了你。它不常用,但用好了就是一把利器。
我个人建议:
- 日常开发用bridge或host模式就够了
- 安全敏感场景,优先考虑None模式
- 需要自定义网络栈时,None模式是唯一选择
记住一句话:None模式不是"没有网络",而是"你来定义网络"。掌握了它,你对Docker网络的理解才算真正到位。