核心是分层排查与配置:先确认是否真被限制卡住,再分别加固容器、dockerd和宿主机三层;通过ulimit -n和ls /proc/1/fd | wc -l对比判断瓶颈,动态扩容用echo写入/proc/$pid/limits,长期方案需在docker run、compose、daemon.json及systemd中统一配置nofile软硬限制至65536。

核心是分层排查与配置:先确认是否真被限制卡住,再分别加固容器、dockerd 和宿主机三层,不能只调大某一层。
快速诊断是不是句柄真耗尽了
进容器执行:
ulimit -n 看软限制(常见默认 1024)
ls /proc/1/fd | wc -l 统计 PID 1 进程当前打开数
两者接近或相等,基本就是瓶颈所在。
同时查宿主机上 dockerd 自身是否也快满了:
cat /proc/$(pgrep dockerd)/limits | grep "Max open files"
ls /proc/$(pgrep dockerd)/fd | wc -l
运行中容器临时扩容(不重启)
适用于紧急恢复,生效快但不持久:
找到容器主进程 PID:
pid=$(docker inspect -f '{{.State.Pid}}'
动态写入新限制(需宿主机 root 权限):
echo -n "65536:65536" > /proc/$pid/limits
验证:
cat /proc/$pid/limits | grep "Max open files"
启动时设好限制(推荐长期方案)
避免每次重启都掉坑里:
• Docker CLI:
docker run --ulimit nofile=65536:65536 ...
• Docker Compose:
在 service 下加:
ulimits:
nofile:
soft: 65536
hard: 65536
• Kubernetes Pod:
在 securityContext.ulimits 中配置同名项
别漏掉 dockerd 和宿主机这俩“上游”
容器限制再大,上游卡死也白搭:
• 修改 /etc/docker/daemon.json,加入:
"default-ulimits": {
"nofile": { "Name": "nofile", "Soft": 65536, "Hard": 65536 }
}
• 同步调整 systemd 对 dockerd 的限制:
在 /etc/systemd/system/docker.service.d/limits.conf 里写:
[Service]
LimitNOFILE=65536
• 重启生效:
sudo systemctl daemon-reload && sudo systemctl restart docker











