MTU 黑洞导致 Docker 容器网络异常处理
标准网络下的虚拟机 MTU 上限通常为 1480,Docker 默认 1500 会导致大包被分片或丢弃。需要把 Docker daemon 与已创建网络的 MTU 都改成 1480。
常见现象
MTU 不匹配的典型表现是「小包通、大包挂」——三次握手正常,业务数据一上量就异常:
curl、wget拉小页面正常,拉大文件中途 hang 住或长时间无进度apt update/apt install、yum、pip、npm拉到一半卡住、超时、Connection resetgit clone在Receiving objects阶段卡死或反复重试- HTTPS 握手能完成,但加载页面长时间空白;HTTP 请求超时但
ping正常 - 容器之间或容器到外网 SSH 能登录但执行
ls大目录、scp大文件就断 - 数据库连接能建立,但跑大结果集查询超时
问题确认
虚拟机内执行:
ip link show eno1 | grep mtu
# 期望看到 mtu 1480
# ip link show en0 | grep mtu # CentOS 系统
ip link show docker0 | grep mtu
# 看到 mtu 1500
或者通过容器执行:
docker run --rm nicolaka/netshoot ping -M do -s 1452 -c 3 8.8.8.8 # 应该通
docker run --rm nicolaka/netshoot ping -M do -s 1453 -c 3 8.8.8.8 # 应该失败:Message too long 或丢包
处理办法
1. 修改 Docker daemon 默认 MTU
编辑 /etc/docker/daemon.json(不存在则新建):
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json > /dev/null <<'EOF'
{
"mtu": 1480
}
EOF
如果文件已存在其他配置,只需在 JSON 中加入 "mtu": 1480 字段,不要整体覆盖。
然后重启 Docker:
sudo systemctl restart docker
确认默认 bridge 网络配置:
docker network inspect bridge | grep -i mtu
# 期望看到 "com.docker.network.driver.mtu": "1480"
2. 已存在的自定义网络
daemon.json 的 mtu 只对默认 bridge 网络生效。已经用 docker network create 创建的网络需要重建,或在创建时显式指定:
docker network create \
--opt com.docker.network.driver.mtu=1480 \
my-net
3. docker-compose 场景
在 docker-compose.yml 中为自定义网络指定 MTU:
networks:
default:
driver: bridge
driver_opts:
com.docker.network.driver.mtu: 1480
验证 MTU 配置
改完后先确认新容器的网卡 MTU 已生效:
docker run --rm nicolaka/netshoot ip link show eth0 | grep mtu
# 期望看到 mtu 1480
再跑一次不分片边界测试,确认 1480 的包能通过,超过 1480 的包会被拦住:
docker run --rm nicolaka/netshoot ping -M do -s 1452 -c 3 8.8.8.8
# -s 1452 = 1480 - 20 (IP头) - 8 (ICMP头),应该通
docker run --rm nicolaka/netshoot ping -M do -s 1453 -c 3 8.8.8.8
# -s 1453 会让 IP 包超过 1480,应该失败:Message too long 或丢包
文档反馈
(如有产品使用问题,请 提交工单)