Docker容器ulimit资源限制
当你的容器应用频繁报 Too many open files 或创建进程失败时,多半是 ulimit 限制不够。
本文讲清 Docker 容器里打开文件数(nofile)和进程数(nproc)的默认来源、调整方式和验证方法,零基础也能直接照做。
容器的 ulimit 从哪里继承
ulimit 是 Linux 对进程资源的限制,常见项就是打开文件数和进程数。
Docker 容器进程默认继承 Docker 守护进程(dockerd)的资源限制,而不是宿主机 shell 里 ulimit -n 查到的值。
容器内默认值经常是 1024 或 65535,高并发应用容易被打开文件数卡住,批量任务又可能被进程数限制误伤。
先看容器当前限制
启动测试容器:
docker run -it --name ulimit-test alpine sh
进入后执行:
ulimit -n
ulimit -u
-n 是打开文件数,-u 是进程数。
退出容器后还能用 inspect 检查:
docker inspect ulimit-test --format '{{json .HostConfig.Ulimits}}'
返回 null 表示没有显式指定,走 Docker 默认策略。
启动时指定 nofile 和 nproc
最直接的方法是在 docker run 时加 --ulimit 参数:
docker run -it --name ulimit-test \
--ulimit nofile=65535:65535 \
--ulimit nproc=65535:65535 \
alpine sh
冒号左边是 soft 限制,右边是 hard 限制。
只写一个数字会同时设置 soft 和 hard。
进入容器后重新执行 ulimit -n 和 ulimit -u 即可看到生效。
用 daemon.json 设置全局默认值
多个容器需要统一限制时,建议写在 /etc/docker/daemon.json,不存在就新建:
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65535,
"Soft": 65535
},
"nproc": {
"Name": "nproc",
"Hard": 65535,
"Soft": 65535
}
}
}
保存后重启 Docker:
systemctl restart docker
注意只影响之后创建的容器,已存在的容器要重建才生效。
排错和避坑要点
docker run 参数优先于 daemon.json,两者都有配置时以启动参数为准。
docker-compose 里也可以写 ulimits 字段,语法类似 JSON 结构。
nproc 按用户维度计算,容器内常用 root 运行,过小的限制也会导致 Resource temporarily unavailable。
调整时先观察实际进程数,不要盲目加大。
不要在容器里直接调 ulimit 改 hard 限制。
容器进程创建时 hard 限制已锁定,普通身份很难放大。
正确做法是重启容器并带上 --ulimit 参数。
host 网络模式要额外注意。
使用 --network host 时,容器进程与宿主机进程共享网络栈,限制也可能受宿主机 systemd、SSH 会话等环境干扰,排查时要两者结合看。
最后验证:进入容器执行 ulimit -n 和 ulimit -u,确认修改后的值;
再用目标应用实际跑一遍触发大量文件或进程的场景。
如果仍然报错,检查应用自身的线程池、连接池或文件句柄缓存配置是否别有限制。