在 Docker 环境中,如果容器访问普通网页、DNS 或小型接口一切正常,但上传文件、拉取镜像、大响应接口或 TLS 握手经常卡住,就要警惕 MTU 不匹配。⚠️ 这类问题常被误判为防火墙、代理或应用超时,实际上可能是数据包超过路径可承载的大小后被丢弃。
一、理解 MTU 不匹配
MTU 是网络接口单次能够传输的最大数据包大小。常规以太网通常使用 1500,但 VPN、VXLAN、云网络、隧道和跨地域专线会增加额外封装头,从而降低可用 MTU。如果容器网卡仍按较大的 MTU 发包,而底层链路只能承载更小的数据包,就可能发生分片、丢包或 Path MTU Discovery 失效。
Docker 的 bridge 网络通过宿主机上的软件网桥和 veth 设备连接容器。容器出口还可能依次经过 docker0、宿主机物理网卡、VPN 接口和云平台虚拟网络,因此排查时不能只检查容器内部。Docker bridge 网络的工作方式及配置选项可参考 Docker 官方文档。
二、典型故障表现
- 小数据包能够正常传输,大文件上传或下载中途停滞。
- 容器可以 ping 通目标,但 curl 请求较大页面时超时。
- SSH 登录正常,SCP、镜像拉取或数据库批量查询失败。
- TCP 连接已经建立,却长时间收不到完整响应。
- 同一服务在宿主机访问正常,在容器内访问异常。
🔎 “小包正常、大包失败”是最有价值的线索。普通 ping 默认载荷较小,即使成功,也不能证明路径能够传输接近 1500 字节的数据包。
三、按链路检查 MTU
首先在宿主机执行 ip link show,记录物理网卡、docker0、VPN、隧道及其他出口接口的 MTU。然后进入故障容器执行 ip link show eth0,确认容器网卡当前值。若容器 eth0 为 1500,而实际出口 VPN 接口更小,就存在明显风险。
接着使用 Docker 命令检查网络配置:docker network inspect 网络名称。重点查看 Driver、Options 和容器接入情况。如果业务使用自定义 bridge,应确认是否设置了 com.docker.network.driver.mtu,不要只修改 docker0 后就认为所有自定义网络都会同步变化。
四、测试实际路径 MTU
Linux 可以通过禁止分片的 ping 逐步探测。例如执行 ping -M do -s 1472 目标地址。IPv4 场景下,1472 字节载荷加上常见的 IP 和 ICMP 头部后,对应 1500 字节数据包。如果失败,可依次尝试 1464、1450、1400 等更小载荷,直到找到能够稳定通过的范围。🧪
测试时应分别从宿主机和容器发起,并选择与真实业务相同的目标地址。若宿主机大包成功而容器失败,应重点检查 Docker 网络;若两者都失败,则继续检查宿主机出口、VPN、云安全设备和中间路由。
注意:ping 失败不一定代表路径不通,目标端可能禁用 ICMP。此时可结合 curl、tcpdump 和实际业务请求交叉验证,避免仅凭单项测试下结论。
五、使用抓包确认丢包位置
在宿主机执行 tcpdump -i any host 目标地址,观察重复 TCP 重传、ICMP fragmentation needed 或 packet too big 等信息。如果持续看到同一序列号重传,却没有确认响应,通常说明数据包在路径中被静默丢弃。
Path MTU Discovery 依赖相关 ICMP 报文通知发送端降低包大小。如果中间防火墙屏蔽了必要的 ICMP 消息,就可能形成 MTU 黑洞。此时不能只调大超时时间,而应修正 MTU,或调整网络设备的 ICMP 策略。
六、修复 Docker 网络配置
调整默认 bridge
可以在宿主机的 /etc/docker/daemon.json 中配置合适的 mtu 值,然后重启 Docker 服务。修改前应备份原文件并检查 JSON 语法。重启可能影响正在运行的容器,应选择维护窗口执行。
调整自定义 bridge
创建网络时可使用 docker network create --driver bridge --opt com.docker.network.driver.mtu=合适数值 网络名称。已有网络通常不能依靠简单编辑稳定地继承新设置,建议创建配置正确的新网络,再重新创建或迁移容器。
如果使用 Compose,可在 networks 配置中通过 driver_opts 指定 com.docker.network.driver.mtu。修改后应重新创建网络和容器,并再次进入容器检查 eth0,确保最终生效,而不是只确认配置文件已经保存。✅
七、选择 MTU 时的原则
- 以真实业务路径中最小的可用 MTU 为依据。
- 预留 VPN、VXLAN、PPPoE 或其他封装所需空间。
- 统一宿主机、Docker 网络和容器网卡的配置逻辑。
- 不要直接照搬他人环境中的固定数值,应通过探测验证。
- 调整后同时测试小请求、大文件、TLS 和长连接业务。
临时进入容器修改 eth0 的 MTU 可用于验证判断,但容器重启或重新创建后通常不会保留,因此不适合作为长期方案。生产环境应把设置固化到 Docker daemon、自定义网络或 Compose 配置中。
总结
排查 Docker 大数据包传输失败,可以按照“识别小包正常大包失败的特征、检查各层接口 MTU、探测路径上限、抓包观察重传与 ICMP、统一 Docker 网络配置、重新创建容器并回归测试”的顺序执行。🚀 核心原则不是盲目把 MTU 改小,而是找出真实路径限制,并让容器发送的数据包大小与底层网络能力保持一致。