3、Docker网络模型:Bridge模式、Host模式、None模式、Overlay网络初探

聊到Docker网络,我脑子里第一个蹦出来的词就是「隔离」。容器之所以是容器,很大程度上靠的就是网络隔离。你想想看,如果每个容器都能随便访问宿主机的网络栈,那还要容器干嘛?直接跑进程不就行了。

Docker提供了几种网络模式,说白了就是给你不同的隔离级别和连通性选择。我个人习惯把Bridge模式当作默认选项,Host模式当作特殊场景的利器,None模式嘛……嗯,它其实挺有用的,只是很多人不知道。

3.1 Bridge模式:默认的隔离方案

Bridge模式是Docker的默认网络模式。你执行 docker run 不加 --network 参数时,用的就是它。

它的工作原理是这样的:Docker Daemon启动时会创建一个虚拟网桥(默认叫 docker0),然后每个容器都会分配一个veth pair(虚拟网卡对),一端在容器里,另一端挂到 docker0 上。容器之间通过这个网桥通信,就像在同一个二层网络里。

核心要点:Bridge模式为每个容器创建独立的网络命名空间,容器拥有自己的IP、路由表、防火墙规则。

我在项目中遇到过一个问题:两个容器都在Bridge模式下,但就是ping不通。排查了半天,发现是宿主机上的iptables规则把FORWARD链给DROP了。Docker虽然会自动添加规则,但如果你自己改了防火墙策略,很容易出问题。

来看一个典型的Bridge网络创建和使用:

# 创建一个自定义Bridge网络
docker network create --driver bridge my-net

# 启动两个容器,连接到同一个网络
docker run -d --name web --network my-net nginx
docker run -d --name db --network my-net mysql

# 从web容器ping db容器
docker exec web ping db

这里有个细节:自定义Bridge网络和默认的 bridge 网络不一样。自定义网络支持容器名解析,默认的不行。也就是说,在自定义网络里,你可以直接用容器名当主机名来通信,默认网络只能靠IP。

我的建议:生产环境一定要用自定义Bridge网络。默认的bridge网络没有DNS解析,容器重启后IP会变,维护起来很痛苦。

3.2 Host模式:性能优先的选择

Host模式就简单粗暴了——容器直接使用宿主机的网络栈,不隔离。容器里的端口就是宿主机的端口,没有NAT转换,没有性能损耗。

为什么会有人用Host模式?说白了就是为了性能。Bridge模式每次网络包都要经过虚拟网桥和iptables,虽然损耗不大,但在高频交易、实时流处理这类场景下,每一微秒都宝贵。

# 使用Host模式启动容器
docker run --network host -d nginx

# 此时访问宿主机80端口,就等于访问容器里的80端口

我记得有一次帮客户做性能压测,他们用Bridge模式跑Redis,QPS死活上不去。换成Host模式后,性能提升了将近15%。这就是网络栈隔离带来的代价。

注意:Host模式下,容器和宿主机共享端口空间。如果你在宿主机上已经占用了80端口,容器里就不能再用80端口了。另外,容器拥有宿主机的全部网络能力,安全风险较高。

Host模式适合的场景:

  • 对网络性能要求极高的应用(Redis、Kafka等)
  • 需要直接操作宿主机网络设备的场景
  • 单机部署,不需要容器间网络隔离

3.3 None模式:完全隔离的沙盒

None模式,顾名思义,就是不给容器配置任何网络。容器里只有一个loopback接口,连不上外网,也连不上其他容器。

你可能会问:「这有什么用?」

嗯,我曾经也觉得None模式很鸡肋,直到有一次需要跑一个离线计算任务。那个任务只需要读取挂载的卷,处理完数据写回去,完全不需要网络。用None模式启动,既安全又轻量。

# 使用None模式启动容器
docker run --network none -d alpine sleep 3600

# 进入容器查看网络
docker exec -it <container_id> ip addr
# 只能看到lo接口

None模式的实际用途:

  • 离线批处理任务
  • 安全敏感的计算(比如加密密钥生成)
  • 作为基础容器,后续手动配置自定义网络

避坑指南:我曾经在CI/CD流水线里用None模式跑单元测试,结果测试用例里有个HTTP请求,直接超时了。排查了半天才发现是网络模式的问题。所以,用None模式前,一定要确认应用真的不需要网络。

3.4 Overlay网络初探:跨主机的通信方案

前面讲的三种模式都局限在单台宿主机上。一旦你开始用Docker Swarm或者Kubernetes,就需要跨主机通信了。这时候,Overlay网络就登场了。

Overlay网络,说白了就是在宿主机网络之上再构建一层虚拟网络。容器看到的IP是Overlay网络的IP,实际数据包会封装在宿主机的网络包里传输。这个过程对容器是透明的。

Docker Swarm模式下创建Overlay网络:

# 初始化Swarm集群
docker swarm init

# 创建Overlay网络
docker network create --driver overlay --attachable my-overlay

# 在不同节点上启动服务
docker service create --name web --network my-overlay --replicas 3 nginx

Overlay网络的核心技术是VXLAN(Virtual Extensible LAN)。它把二层数据帧封装在UDP包里,通过三层网络传输。这样,即使容器分布在不同的物理机上,也能像在同一个二层网络里一样通信。

关键点:Overlay网络解决了容器跨主机通信的问题,但代价是额外的封装和解封装开销。在万兆网络环境下,这个开销大约在5%-10%之间。

我记得在给一个金融客户做POC时,他们担心Overlay网络的性能。我们做了对比测试:Bridge模式下的TCP吞吐量是9.2Gbps,Overlay模式是8.5Gbps。客户觉得可以接受,毕竟换来的是跨主机通信的便利性。

Overlay网络的几个特点:

  • 跨主机通信,容器IP不依赖宿主机网络
  • 支持服务发现和负载均衡(Swarm模式下)
  • 加密传输(可以启用IPSec)
  • 性能损耗在可接受范围内

注意:Overlay网络依赖键值存储(如etcd、consul)来维护网络状态。如果这个存储挂了,整个Overlay网络都会出问题。生产环境一定要做好高可用。

3.5 四种模式的对比与选择

说了这么多,到底该用哪种模式?我整理了一个表格,方便你对比:

模式 隔离性 性能 跨主机 适用场景
Bridge 中等 单机多容器部署
Host 最高 高性能应用、网络设备操作
None 最高 无网络 离线任务、安全沙盒
Overlay 中等(有损耗) 容器集群、微服务

选择建议:

  • 单机开发测试,用Bridge模式就够了
  • 追求极致性能,用Host模式,但要注意安全
  • 完全不需要网络的任务,用None模式
  • 多机集群部署,用Overlay网络

最后说一句,网络模式的选择没有银弹。我在不同项目里用过不同的组合,有时候甚至会在同一个应用里混合使用。比如,数据面用Host模式追求性能,管理面用Bridge模式保证隔离。关键是要理解每种模式的原理和代价,然后根据实际需求做取舍。