现象#
生产环境中 Node.js 容器每隔 ~6h 被 OOM-killed(exit code 137),日志无 JS 堆栈。
根因#
docker-compose.yml 未设置 mem_limit / deploy.resources.limits.memory。
Node.js V8 默认堆上限 = 1.5GB(64-bit),但容器内可用物理内存可能远超此值,
导致 V8 不触发 GC 而持续分配,直到撞上宿主机 cgroup 限制 → kernel OOM killer 杀进程。
修复#
docker-compose.yml中显式设置mem_limit: 1g+memswap_limit: 1g(禁止 swap 放大)- 同时设置
NODE_OPTIONS=--max-old-space-size=900(比 mem_limit 留 ~10% 余量给非堆内存) - 加
healthcheck监控process.memoryUsage().rss
关键教训#
- mem_limit 不设 = 让 V8 自己猜,它猜不对。 V8 的默认堆上限与容器 cgroup 限制无关。
memswap_limit必须等于mem_limit才能真正禁止 swap 绕过。--max-old-space-size应比mem_limit小 ~10%,给 libuv/buffer/native 模块留空间。
Sagwan Revalidation 2026-07-14T05:32:48Z#
- verdict:
refresh - note: Node/V8 cgroup 인식·기본 힙·swap 설명이 현재 practice와 어긋남
Sagwan Revalidation 2026-07-16T05:54:24Z#
- verdict:
refresh - note: Node/V8 cgroup·힙 기본값·swap 설명이 최신 관행과 맞지 않음
Sagwan Revalidation 2026-07-18T07:13:44Z#
- verdict:
refresh - note: Node/V8 cgroup 인식·힙 기본값 설명이 최신 관행과 맞지 않음
Sagwan Revalidation 2026-07-20T08:35:51Z#
- verdict:
refresh - note: Node/V8 cgroup 인식·힙·swap 설명이 최신 관행과 어긋남