根本原因是MTU不匹配:TLS握手需数百至上千字节大包,而路径中某环节(如云主机网卡MTU=1450)小于容器默认1500,导致大包被静默丢弃,握手超时;可通过ping -M do -s探测路径MTU,并在daemon.json中设"mtu"为适配值(如1400)后重启Docker解决。

HTTPS 请求挂起(表现为 net/http: TLS handshake timeout),而 ping 和 HTTP 明文请求正常,大概率是 MTU 不匹配导致的。根本原因在于:TLS 握手需传输几百至上千字节的数据包,当路径中某环节(如云主机网卡、虚拟交换机、隧道封装)的 MTU 小于容器默认的 1500 时,大包会被静默丢弃,握手无法完成。
快速确认是否为 MTU 问题
进容器执行路径 MTU 探测:
- 运行
ping -M do -s 1472 目标域名或IP(1472 + 28 字节头 = 1500 字节) - 若返回
Packet too big或无响应,说明路径 MTU - 逐步降低
-s值(如 1420 → 1372 → 1320),直到能通 - 能通的最大
-s值 + 28 ≈ 实际路径 MTU(例如 1420 + 28 = 1448 → 取整为 1450)
统一 Docker 全局 MTU(推荐)
修改 Docker 守护进程配置,让所有新建容器自动适配:
- 编辑
/etc/docker/daemon.json,加入或修改"mtu"字段 - 值设为探测到的路径 MTU(如
1450),或更保守的1400或1300 - 保存后执行:
sudo systemctl daemon-reload && sudo systemctl restart docker - 注意:重启会终止所有运行中容器,需重新启动服务
为特定网络单独设置 MTU
不改动全局配置时,可创建带自定义 MTU 的桥接网络:
- 命令创建:
docker network create --opt com.docker.network.driver.mtu=1450 mynet - 启动容器时指定:
docker run --network mynet ... - 已有容器可通过
docker network connect mynet <container></container>加入 - 适用于多环境共存(如部分容器需 1500,部分需 1450)
检查与验证
操作后务必验证效果:
- 进容器执行
ip link show eth0 | grep mtu,确认值已生效 - 用
curl -v https://example.com测试 TLS 握手是否秒级完成 - 观察业务日志中是否还有
TLS handshake timeout报错 - 若仍失败,再检查宿主机防火墙、DNS、代理等其他干扰项


















