Docker 网络进阶实战:从自定义 bridge、macvlan 到多主机 overlay 的完整选型指南 原创
为什么单主机网络不够用
当 Docker 应用从单机走向多机集群时,默认的 bridge 网络立即暴露出局限性:每个容器的 IP 只在宿主机内可见,跨主机的容器无法直接用容器 IP 通信,服务发现与负载均衡也失去意义。本文从网络模型出发,拆解 Docker 从 bridge 到 overlay 的完整演进路径,并给出生产环境下的选型建议。
Linux 网络命名空间与 Docker 网络的底层
Docker 网络的核心是 Linux 的 网络命名空间(network namespace)。每个容器拥有独立的网络栈(网卡、路由表、iptables 规则),宿主机通过 veth 对(虚拟以太网对)把容器连接到宿主机网桥。理解这一层,才能理解为什么 docker run --network 能自由切换网络模式。
| 网络模式 | 隔离性 | 典型场景 |
|---|---|---|
| bridge | 容器间隔离 | 单机多容器 |
| host | 共享宿主机网络栈 | 高性能低延迟服务 |
| none | 完全隔离 | 高安全敏感任务 |
| overlay | 跨主机 | Swarm / K8s 集群 |
自定义 bridge 网络:脱离默认网络的依赖
默认的 docker0 网桥存在诸多问题:IP 段固定、无 DNS 解析、容器间依赖 --link。更推荐的做法是创建自定义 bridge 网络,它内置嵌入式 DNS,容器间可以通过名称而非 IP 通信。
# 创建自定义 bridge 网络
docker network create --driver bridge --subnet 172.20.0.0/16 my-net
# 启动容器时指定网络
docker run -d --network my-net --name web nginx
docker run -d --network my-net --name db mysql
# 容器内直接通过名称访问
# web 容器访问 db:db:3306
macvlan:让容器获得真实二层 IP
如果业务需要容器像独立物理机一样直接暴露在局域网(例如需要真实 MAC 地址参与二层通信),macvlan 模式最合适。每个容器获得一个与宿主机同网段的 IP,走真实的物理网卡收发数据。
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 my-macvlan
docker run -d --network my-macvlan --ip 192.168.1.50 nginx
注意:macvlan 模式下宿主机与容器无法直接通信(隔离冲突),需要额外接入一个 dummy 网桥来解决,这一坑在生产中极易踩到。
overlay 网络:跨主机的容器编排基础
overlay 网络让不同宿主机上的容器共享一个虚拟网段,是 Docker Swarm 和 Kubernetes 网络的基础。它通过 VXLAN 隧道封装二层数据,在物理网络上叠加一个逻辑网络。
# 初始化 Swarm 集群后创建 overlay 网络
docker swarm init
docker network create -d overlay --attachable my-overlay
# 在不同节点启动服务
docker service create --network my-overlay --name app nginx
overlay 需要 --attachable 参数才能被普通 docker run 容器接入,这是 Swarm 服务与独立容器混合部署时的常见遗漏。
网络隔离与安全加固
生产环境应遵循最小暴露原则:数据库、缓存等服务放入内部网络,只通过应用层网络对外暴露。结合 iptables 默认策略与 Docker 的 --icc=false(禁止容器间默认通信)可以显著降低横向攻击风险。
# 禁止容器间默认互相访问,只允许通过 --link 显式放行
docker run -d --network my-net --icc=false --name db mysql
选型总结
单机多容器选自定义 bridge;需要局域网真实 IP 选 macvlan;跨主机编排选 overlay。网络模式没有银弹,核心是理解命名空间与隧道封装的原理,再结合业务拓扑做取舍。生产环境务必提前规划网段,避免 IP 冲突与路由混乱。