根本原因是json-file驱动在高并发下引发宿主机文件锁竞争,导致I/O阻塞、容器卡死或重启;应切换为local驱动(二进制+内存映射+自动轮转)或syslog/fluentd外发日志,同时禁用非核心服务日志、控制日志级别、隔离存储路径并优化启停策略。

这问题本质不是“压测太猛”,而是 Docker Compose 默认日志驱动(json-file)在高并发写入时,多个容器争抢同一宿主机上的日志文件句柄,触发内核级文件锁竞争——轻则写延迟飙升,重则 docker-compose up 卡死、容器反复重启、日志丢失甚至 dockerd 进程僵住。
换掉 json-file 日志驱动
这是最直接有效的根治手段。json-file 为每个容器维护一个独立日志文件,压测时数百个容器同时刷日志,宿主机 I/O 和文件系统锁压力陡增。
- 改用
local驱动:它专为高性能设计,使用二进制格式 + 内存映射 + 自动轮转,无文件锁争抢logging:<br> driver: "local"<br> options:<br> max-size: "50m"<br> max-file: "5"
- 若需对接日志平台(如 Loki、ELK),优先用
syslog或fluentd驱动,把日志直接发走,不落地到本地磁盘
禁用日志收集或限制日志量
压测关注的是服务响应和资源消耗,不是每条 debug 日志。
- 对非核心服务(如 mock 数据库、stub 网关)关闭日志:
logging: driver: "none" - 对应用服务启用日志级别控制(如 Laravel 的
LOG_LEVEL=warning,Spring Boot 的logging.level.root=WARN),从源头减少日志生成量 - 避免在压测中开启
debug或trace级别,这类日志量常呈指数增长
隔离日志存储路径
即使保留 json-file,也要避免所有容器日志挤在同一个挂载点(如 /var/lib/docker/containers)。
- 用命名卷单独管理压测服务日志:
volumes: [app-logs:/var/log/app],Docker 卷层有更优的并发写入策略 - 若必须绑定挂载,确保挂载目录位于独立 SSD 分区,并设置
noatime,nobarrier等挂载选项提升 I/O 效率 - 检查 inode 使用率:
df -i,压测中大量小日志文件极易耗尽 inode,导致 “No space left on device” 错误
调整 Compose 启动与销毁行为
压测常伴随高频启停,而容器销毁阶段的日志 flush 是锁冲突高发环节。
- 加
stop_grace_period: 5s,避免默认 10s 等待导致日志未刷完就被强制 kill - 启动前加
restart: "no",禁用自动重启——压测中容器崩溃应立刻暴露问题,而非反复拉起加剧锁竞争 - 用
docker compose down --volumes替代up --force-recreate,显式清理旧状态,避免残留日志文件句柄被新容器继承


















