Docker 网络模式详解实战:bridge、host 与容器互通排障

很多个人站长开始用 Docker 之后,遇到的第一个坎往往不是镜像怎么构建,而是网络怎么不通:容器里能访问外网,外面却访问不到容器;两个容器明明在同一个宿主机上,互相之间就是 ping 不通;换了一台服务器之后,端口映射又莫名其妙失效了。这些问题十有八九都出在对 Docker 网络模式的理解上。这篇文章把 Docker 的几种网络模式从头到尾讲清楚,包括它们的工作原理、适用场景和常见故障的排查方法,看完之后你就能自己解决绝大多数容器网络问题。

一、先搞清楚 Docker 网络的整体架构

Docker 的网络能力并不是容器自己实现的,而是由 Docker 守护进程配合 Linux 内核的网络特性(网络命名空间、veth 虚拟网卡、网桥、iptables 等)共同搭建出来的。每启动一个容器,Docker 都会为它创建一套独立的网络命名空间,让容器拥有自己的 IP 地址、路由表和防火墙规则,看起来就像一台独立的小主机。Docker 内置了四种单机网络模式:bridge、host、none 和 container,另外还有用于跨主机集群的 overlay 模式。默认情况下,docker run 不指定网络参数时使用的就是 bridge 模式。

二、bridge 模式:默认网络的工作原理

安装完 Docker 之后,你在宿主机上执行 ip addr 命令,会看到一个名为 docker0 的网桥设备,默认 IP 段是 172.17.0.0/16。docker0 本质上是一个 Linux 网桥,所有默认网络下的容器都会通过一对 veth 虚拟网卡挂到 docker0 上。veth 是成对出现的,一头在容器内部,另一头接在 docker0 上,数据包在两者之间直接转发。容器启动时,Docker 会从 docker0 的地址池里给容器分配一个 172.17.0.x 的 IP,同时设置默认网关为 172.17.0.1,也就是 docker0 本身。容器访问外网时,数据包到达 docker0 之后,由 iptables 的 NAT 规则做源地址转换(MASQUERADE),把容器的内网 IP 换成宿主机的外网 IP 发出去,返回的包再按连接跟踪记录转回容器。这套机制和家用路由器非常像,理解了这个模型,bridge 模式的大部分行为就都能解释了。

三、自定义 bridge 网络:生产环境的首选

虽然 docker0 开箱即用,但生产环境我更推荐创建自定义 bridge 网络,原因有两个。第一,自定义网络自带内置 DNS 解析:同一网络下的容器可以直接用容器名互相访问,比如在 web 容器里访问 mysql 容器只需要 curl http://mysql:3306,不用去记容易变的 IP 地址。第二,docker0 上的容器默认不做 DNS 互解析,只能靠 --link 之类的老办法,而 --link 早就被官方标记为废弃特性了。创建自定义网络和执行容器接入的命令如下:

docker network create --driver bridge myweb
docker run -d --name mysql --network myweb mysql:8.0
docker run -d --name web --network myweb -p 8080:80 nginx

创建好之后,可以用 docker network inspect myweb 查看网络详情,里面会列出所有接入的容器以及各自的 IP。要注意的是,不同网络之间的容器默认是隔离的,即使在同一台宿主机上也互相访问不到,这是 Docker 的安全设计,需要跨网络通信时可以把容器同时加入多个网络,或者用网络连通命令 docker network connect 把某个容器再接入另一个网络。

四、host 模式:牺牲隔离换取性能

host 模式用 --network host 启动容器,容器不会创建自己的网络命名空间,而是直接使用宿主机的网络栈。这意味着容器里的进程监听某个端口,就相当于宿主机直接监听该端口,不需要也不支持 -p 端口映射参数。host 模式最大的优势是性能好、延迟低,因为没有 NAT 和网桥转发这一层开销,同时端口不会冲突的话配置也简单。但它牺牲了网络隔离,容器可以访问宿主机所有的网络资源,安全边界变模糊了。适合的场景是:对网络性能要求很高的应用、需要绑定大量端口的服务(比如一些 RPC 服务)、以及容器内要使用宿主机特定网卡 IP 的场景。个人站长的网站服务一般用不到 host 模式,bridge 模式足够,但理解它有助于看懂别人写的 Dockerfile 和部署脚本。

五、none 模式与 container 模式

none 模式(--network none)表示容器完全没有网络,只有一个回环接口 lo,适合对安全性要求极高、完全不需要网络的应用,比如离线计算任务、纯本地文件处理。container 模式(--network container:容器名)则是让新容器与指定容器共享同一个网络命名空间,两者共用 IP 和端口,典型用途是网络调试:比如用 --network container:web 启动一个带 curl、ping、tcpdump 等工具的调试容器,就可以直接观察 web 容器的网络流量,而不需要往生产镜像里塞调试工具。这两种模式使用频率不高,但排障时非常有用。

六、端口映射的完整姿势

要让外部访问容器里的服务,就得做端口映射。最常用的是 -p 宿主机端口:容器端口,比如 -p 8080:80 把宿主机的 8080 端口转发到容器的 80 端口。几个实用细节:第一,可以一次映射多个端口,-p 8080:80 -p 443:443;第二,可以只绑定特定地址,-p 127.0.0.1:8080:80 表示只有本机能访问,外网访问不到,这个技巧常用于把数据库、Redis 这类服务只暴露给本机,避免直接暴露公网;第三,-P(大写)会自动把所有 EXPOSE 过的端口映射到宿主机的随机高位端口,配合 docker port 容器名 可以查看映射结果。映射完成后,外部请求经过 iptables 的 DNAT 规则转发到容器,这也是为什么修改防火墙规则时容易和 Docker 的 iptables 管理产生冲突。

七、常见故障一:容器之间 ping 不通、连不上

容器间通信失败是最常见的问题。排查思路按顺序来:先用 docker network inspect 确认两个容器是否在同一个网络里,不在同一个网络就是设计问题,把它们加入同一网络即可;在同一个网络还连不上,就进容器里用 docker exec -it 容器名 sh 执行 ping 对方容器名 测试 DNS 解析和连通性,如果 ping 容器名不通但 ping IP 通,说明内置 DNS 出了问题,重启 Docker 服务或者重建容器一般能解决;如果连 IP 都 ping 不通,检查宿主机上 docker0 网桥是否存在,service docker restart 重启守护进程后通常能恢复。另外要提醒一句:很多基础镜像里根本没有 ping 命令,遇到 command not found 不代表网络不通,改用 curl 或者 wget 测试更可靠。

八、常见故障二:端口映射不生效、外部访问不到

端口映射失效的原因通常有三个。第一,容器内的服务监听地址不是 0.0.0.0,比如 MySQL 默认只监听 127.0.0.1,容器外自然访问不到,需要在容器内把 bind-address 改成 0.0.0.0 或指定网卡。第二,宿主机防火墙挡住了映射端口,尤其是 CentOS 系服务器的 firewalld,或者云服务商安全组没放行,注意排查的顺序是云安全组、宿主机防火墙、Docker 本身。第三,Docker 的 iptables 规则被清空或覆盖了,这种情况常见于手动执行了 iptables -F 清空规则,或者 ufw 等防火墙工具与 Docker 冲突,重启 Docker 服务让它重新生成规则即可。用 iptables -t nat -L -n 可以查看 DNAT 规则是否还在。

九、常见故障三:VPS 上网络不稳、MTU 不匹配

这是一个很隐蔽的坑:很多 VPS 的物理网卡 MTU 是 1450(比如某些隧道网络),而 Docker 默认给 docker0 设置的 MTU 是 1500,导致大数据包在网桥转发时被丢弃,表现就是小流量正常、大文件传输或者 HTTPS 握手时随机卡死。解决办法是在 /etc/docker/daemon.json 里统一设置 MTU:

{
  "mtu": 1450
}

改完之后重启 Docker:systemctl restart docker。注意 daemon.json 的修改会影响之后新建的网络和容器,已经存在的网络需要删除重建才生效。判断是不是 MTU 问题,可以在容器里执行 ping -M do -s 1472 网关IP,如果报错说需要分片而无法分片,基本就能确定是 MTU 不匹配。

十、跨主机通信与 overlay 网络简介

当网站规模大到需要多台服务器跑容器集群时,单机网络模式就不够用了,这时要用 overlay 网络。overlay 是 Docker Swarm 模式下的跨主机网络,它利用 VXLAN 隧道技术把多台主机的容器网络打通,让不同机器上的容器像在同一个局域网里一样通信,同时保留内置 DNS。启用方式很简单:先把多台机器加入同一个 Swarm 集群,然后 docker network create -d overlay 集群网络名,在这个网络里启动的容器就可以跨主机互访了。对于个人站长来说,业务量没到那个级别之前不用急着上 Swarm 和 Kubernetes,单机 Docker 加自定义 bridge 网络完全够用,但了解一下概念,以后迁移到集群架构时不至于两眼一抹黑。

十一、安全提醒:别把容器直接暴露到公网

最后聊几句安全。端口映射是双刃剑,把端口暴露到 0.0.0.0 意味着公网任何人都能尝试连接。个人站长的服务器上,数据库、Redis、消息队列这类服务务必只映射到 127.0.0.1,需要远程访问时走 SSH 隧道而不是直接开公网端口。另外,不要用 root 用户跑容器进程,不要给容器挂载宿主机的敏感目录(比如 /etc、/root),容器逃逸漏洞虽然不常见,但一旦发生后果严重。docker ps -a 定期检查有没有多余的容器在运行,docker system prune 清理掉不用的镜像和容器,保持环境干净,出问题的概率就会小很多。

十二、总结

Docker 网络其实没有想象中复杂:单机场景下,默认的 bridge 模式负责 NAT 上网,自定义 bridge 提供容器名互访,host 模式牺牲隔离换性能,none 和 container 模式服务于特殊场景;多机场景下用 overlay 打通跨主机通信。遇到问题按照"先看网络归属、再测 DNS、后查防火墙和 MTU"的顺序排查,绝大多数故障都能快速定位。把这几种模式的关系理清楚,你的容器化网站就成功了一大半。

Last modification:August 29th, 2026 at 08:07 am

Leave a Comment