根本原因是默认 max-concurrent-downloads 和 max-concurrent-uploads 过小(仅3),导致高并发拉镜像时请求排队等待下载锁,表现为“无报错但卡在 pulling”;需调大该值并监控 I/O。

为什么 dockerd 在高并发拉取镜像时卡住?
根本原因不是 CPU 或内存打满,而是默认的 max-concurrent-downloads 和 max-concurrent-uploads 太保守(默认 3)。当批量启动容器或 CI 流水线并发拉镜像时,大量请求排队等待下载锁,表现为「没报错但一直卡在 pulling」。
实操建议:
- 修改
/etc/docker/daemon.json,增加:{ "max-concurrent-downloads": 10, "max-concurrent-uploads": 10 } - 重启生效:
sudo systemctl restart docker - 注意:值设太高可能压垮镜像仓库或本地磁盘 I/O,建议从 5 开始逐步调高,配合
iostat -x 1观察 %util
dockerd 启动慢、响应延迟高的常见配置冲突
典型现象是执行 docker info 要等 3–5 秒,或者 docker ps 偶发超时。大概率是启用了某些低效后端或网络探测机制。
实操建议:
- 禁用 IPv6 自动探测(除非真用 IPv6):
"ipv6": false,避免 daemon 启动时阻塞等待 IPv6 路由就绪 - 关闭
live-restore(如果没做容器热恢复需求):"live-restore": false,否则每次 dockerd 重启都会扫描全量容器状态 - 检查
registry-mirrors配置——若镜像源不可达或响应慢,dockerd会在后台持续重试,拖慢所有 API 响应
并发构建时 docker build 抢占 buildkit 资源导致失败
启用 BuildKit 后,并发 docker build 默认共享同一套构建缓存和 worker 池。一旦某个大镜像构建占满内存或磁盘缓存,其他构建会因 failed to compute cache key 或 context deadline exceeded 中断。
实操建议:
- 为不同构建任务分配独立缓存命名空间:
DOCKER_BUILDKIT=1 docker build --cache-from type=local,src=/tmp/cache-a ... - 限制单个构建的资源上限(需 Docker 24.0+):
--memory=2g --cpus=2,防止一个构建吃光宿主机资源 - 避免在 CI 中无节制启用
DOCKER_BUILDKIT=1——老版本 BuildKit 对多阶段构建的并发支持不稳,反而比经典 builder 更容易死锁
容器启动延迟突增,其实是 containerd 的 shim 进程创建瓶颈
dockerd 本身不直接运行容器,它委托给 containerd;而 containerd 每启一个容器,就要 fork 一个 containerd-shim 进程。在低配机器或 SELinux 强制模式下,进程 fork + 安全上下文初始化可能成为瓶颈。
实操建议:
- 确认
containerd版本 ≥ 1.6 —— 1.5 及以前在高并发场景下 shim 创建有已知锁竞争问题 - 若用 SELinux,避免频繁切换策略:临时关闭验证测试是否改善延迟:
sudo setenforce 0(仅用于定位) - 监控
containerd-shim进程数:ps aux | grep containerd-shim | wc -l,持续超过 200 且增长不收敛,说明存在容器未正常退出或 shim 泄漏
真正难调的点不在参数开关,而在各层之间资源视角错位:dockerd 看的是并发数,containerd 看的是 shim 进程负载,而内核看到的是 fork 数和 cgroup 压力。调参前务必先用 strace -p $(pgrep dockerd) 确认卡在哪一环。











