帮助中心 >  技术知识库 >  云服务器 >  服务器教程 >  Docker 容器内存持续增长排查实战:如何快速定位内存泄漏

Docker 容器内存持续增长排查实战:如何快速定位内存泄漏

2026-07-15 17:02:54 66

Docker 容器内存持续增长排查实战:如何快速定位内存泄漏

生产环境中,经常会遇到这样的告警:

Docker Host 内存使用率达到95%

容器没有重启,但内存持续上涨

业务响应越来越慢

很多运维人员第一反应就是重启容器,但如果没有找到真正原因,问题很快又会再次出现。下面介绍一套生产环境常用的排查方法。

确认是主机内存还是容器内存

首先查看宿主机内存:

free -h

例如:

               total        used        free      shared  buff/cache

Mem:            32Gi        28Gi       1.2Gi        256Mi       2.8Gi

然后查看所有容器资源使用情况:

docker stats --no-stream

输出:

CONTAINER ID   NAME       MEM USAGE / LIMIT

f8b6d8d8f2a1   nginx       45Mi / 1Gi

9a74c6a7de32   redis       520Mi / 2Gi

31c97a34d621   java-api    9.6Gi / 10Gi

很容易发现哪个容器占用了大量内存。

查看容器内实际进程

进入容器:

docker exec -it java-api bash

如果没有 bash:

docker exec -it java-api sh

查看内存占用:

ps -eo pid,comm,%mem,%cpu --sort=-%mem | head

例如:

PID COMMAND %MEM %CPU

1   java    92.1  380

说明问题集中在 Java 进程。

如果是 Python:

python

gunicorn

uwsgi

也可以快速定位。

判断是否是缓存导致

Linux 会使用空闲内存作为文件缓存。

查看:

cat /proc/meminfo

重点关注:

MemFree

Cached

Buffers

SReclaimable

如果:

Cached: 12GB

说明大量内存属于缓存,而不是应用真正占用。

进一步查看:

slabtop

确认是否为 Slab Cache 增长。

检查容器 OOM 记录

查看容器是否触发过 OOM:

docker inspect java-api | grep -i OOM

或者:

dmesg | grep -i "Killed process"

例如:

Out of memory:

Killed process 3567 (java)

说明内存已经耗尽,被内核强制终止。

查看 Cgroup 内存统计

Docker 使用 Cgroup 管理资源。

查看:

cat /sys/fs/cgroup/memory/docker//memory.usage_in_bytes

Cgroup v2:

cat /sys/fs/cgroup//memory.current

查看限制:

cat /sys/fs/cgroup//memory.max

能够确认:

实际使用内存

限制内存

是否接近上限

检查是否存在内存泄漏

如果是 Java:

jcmd GC.heap_info

或者:

jmap -histo | head -30

查看对象数量:

byte[]

HashMap

String

如果对象持续增长,就需要进一步分析 Heap Dump。

Python 可使用:

python -m tracemalloc

Go 程序:

curl http://www.landui.com:6060/debug/pprof/heap

结合 pprof 分析内存分配。

设置合理的资源限制

很多生产环境没有限制容器内存。

例如:

docker run nginx

推荐:

docker run \\

--memory=2g \\

--memory-swap=2g \\

--cpus=2 \\

nginx

Docker Compose:

services:

  api:

    image: my-api

    deploy:

      resources:

        limits:

          memory: 2G

即使程序发生内存泄漏,也不会拖垮整台宿主机。

持续监控容器内存

每分钟记录一次资源使用:

while true

do

    docker stats --no-stream >> /var/log/docker_mem.log

    sleep 60

done

统计增长最快的容器:

grep "java-api" /var/log/docker_mem.log

结合 Prometheus + cAdvisor + Grafana,可以长期监控:

Container Memory Usage

RSS

Cache

Working Set

OOM Count

比出现故障后再排查更有效。

生产环境案例

某业务服务器部署了:

Docker

Nginx

Redis

Java API

凌晨开始内存持续上涨:

32GB

 

31GB

 

 

30GB

 

 

OOM

最初怀疑是 Redis,但通过:

docker stats

发现:

Redis:600MB

 

Nginx:80MB

 

Java:14GB

进一步分析 Heap Dump,发现缓存对象未设置过期时间,大量 HashMap 长期驻留内存。

优化后:

· 增加缓存淘汰策略。

· 设置 JVM 最大堆大小。

· 为容器配置 --memory 限制。

· 接入 Prometheus 持续监控。

优化完成后:

容器内存稳定在 3.5GB~4GB

连续运行两个月无 OOM

宿主机内存使用率保持在 60% 以下

Docker 运维中,内存持续增长并不一定意味着宿主机故障,也可能是应用缓存、内存泄漏或资源限制配置不合理导致。通过 docker statsCgroup、应用内存分析工具以及持续监控相结合,才能快速定位问题根源,而不是依赖重启容器来暂时掩盖问题。

 


提交成功!非常感谢您的反馈,我们会继续努力做到更好!

这条文档是否有帮助解决问题?

非常抱歉未能帮助到您。为了给您提供更好的服务,我们很需要您进一步的反馈信息:

在文档使用中是否遇到以下问题:
XML 地图