bigywater.tech
Docker · 57

网络 MTU:包太大被丢弃的现象

MTU 不匹配会让连接莫名其妙地卡住或变慢。这篇看 Docker Desktop 的默认 MTU 是多少,怎么给自定义网络设置 MTU,以及它怎样变成 TCP 的 MSS。

65535
Docker Desktop 里默认容器 eth0 的 MTU(常见物理网络是 1500)
1348
MTU 1400 的自定义网络里两个容器之间 TCP 连接的 MSS
32741
默认 bridge(MTU 65535)上两个容器之间的 MSS

默认值

实测 · 本机执行输出
  虚拟机 eth0 / docker0 的 MTU:65535 65535
  默认 bridge 的网络选项 com.docker.network.driver.mtu = 65535
  默认容器里 eth0 的 MTU = 65535

Docker Desktop 虚拟机内部的网络 MTU 是 65535,默认 bridge 和容器都继承了这个值。Linux 宿主机上的默认是 1500,这是我知道的惯例,没有在这里验证。

设置 MTU

实测 · 本机执行输出
  -o com.docker.network.driver.mtu=1400:容器里 eth0 的 MTU = 1400;虚拟机里这个网络的网桥 br-03b2… 的 MTU = 1400
  -o com.docker.network.driver.mtu=1280:容器里 eth0 的 MTU = 1280;虚拟机里这个网络的网桥 br-6972… 的 MTU = 1280

创建网络时用 -o com.docker.network.driver.mtu=1400,容器里的 eth0 和虚拟机里的网桥都变成 1400。当容器要经过 VPN、隧道之类有更小 MTU 的链路时,通常要这样降 MTU;我没有复现一个真实的 MTU 黑洞问题。

MSS

实测 · 本机执行输出
  默认 bridge(MTU 65535):两个容器之间的 TCP MSS = 32741
  自定义网络 MTU 1400:两个容器之间的 TCP MSS = 1348
  自定义网络 MTU 1280:两个容器之间的 TCP MSS = 1228

读 TCP_MAXSEG 看到:MTU 1400 → 1348,MTU 1280 → 1228,都是 MTU 减 52;默认 65535 的网络上是 32741,不是 65483,具体原因我没有查。我试过让容器连外网地址(github.com:443)读 MSS,连接超时了,所以没有外网路径上的数据。

分步演示

网络 MTU
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。MTU 取自 /sys/class/net/*/mtu;MSS 用 Python 的 getsockopt(IPPROTO_TCP, TCP_MAXSEG) 在建立连接后读取;每种配置运行一次;实验后已删除容器和网络
    • 没有验证:外网路径上的 MSS 与路径 MTU 发现、VPN 下的 MTU 黑洞、IPv6 的最小 MTU 1280 限制、ping -M do 分片测试、overlay / macvlan 网络、Linux 宿主机上的默认 MTU
    京ICP备2026067502号-1京公网安备11010502063487号