Docker 容器异常重启排查
·
一、问题现象
常见现象:
-
Docker 容器运行一段时间后自动重启
-
docker ps查看:
docker ps
发现:
STATUS: Up 几分钟
但是:
CREATED: 几天前
说明:
容器不是新创建,而是运行期间发生过重启。
二、第一步:确认容器是否重启过
查看重启次数:
docker inspect self_service | grep -A10 RestartCount
示例:
"RestartCount": 6
说明:
-
容器已经异常退出并被 Docker 自动拉起多次。
如果:
"RestartCount": 0
说明:
可能是:
-
Docker服务重启
-
宿主机重启
-
人工启动
三、第二步:查看容器状态
执行:
docker inspect self_service | grep -A20 State
重点关注:
1. ExitCode
例如:
"ExitCode": 137
表示:
容器收到:
SIGKILL
通常原因:
-
内存不足
-
OOM Killer杀进程
2. OOMKilled
例如:
"OOMKilled": true
表示:
Docker确认发生OOM。
注意:
部分 Docker/containerd 版本可能显示:
"OOMKilled": false
但实际发生OOM。
需要结合:
docker events
判断。
四、第三步:查看 Docker 事件(最关键)
执行:
docker events --since 24h
重点关注:
OOM
例如:
container oom self_service
说明:
容器发生内存不足。
容器退出
例如:
container die
exitCode=137
说明:
进程被强制杀死。
自动恢复
例如:
container start
说明:
Docker根据restart策略自动启动。
五、判断OOM完整链路
典型OOM流程:
Java进程内存增长
|
|
v
超过Docker限制
|
|
v
Linux OOM Killer执行kill -9
|
|
v
容器退出(exitCode=137)
|
|
v
Docker restart策略重新启动
六、第四步:查看容器日志
查看最近日志:
docker logs --tail=300 self_service
查看指定时间:
docker logs \
--since "2026-08-10 14:40:00" \
self_service
重点搜索:
Java Heap OOM
java.lang.OutOfMemoryError:
Java heap space
表示:
Java堆内存不足。
Metaspace不足
OutOfMemoryError:
Metaspace
表示:
类元空间不足。
DirectMemory不足
OutOfMemoryError:
Direct buffer memory
表示:
NIO堆外内存不足。
七、第五步:查看容器内存限制
执行:
docker inspect self_service | grep -i memory
例如:
"Memory": 2147483648
代表:
2GB限制。
换算:
2147483648 bytes ≈ 2GB
查看启动参数:
docker inspect self_service | grep Cmd -A10
检查:
--memory
--memory-swap
八、Java容器内存计算方法
注意:
Java实际占用:
Java总内存 =
Heap
+
Metaspace
+
DirectMemory
+
线程栈
+
CodeCache
+
Native Memory
不是只有:
-Xmx
例如:
配置:
-Xmx2048m
-XX:MaxMetaspaceSize=384m
-XX:MaxDirectMemorySize=512m
理论:
Heap:
2048M
Metaspace:
384M
Direct:
512M
其它:
300~600M
总计:
约3.2G~3.5G
因此:
4G容器比较合理。
九、检查宿主机是否整体内存不足
查看:
free -h
查看:
top
查看OOM记录:
journalctl -k | grep -i oom
或者:
dmesg | grep -i killed
如果出现:
Out of memory:
Killed process xxxx(java)
说明:
宿主机内核杀进程。
十、查看实时内存使用
执行:
docker stats self_service
观察:
例如:
MEM USAGE / LIMIT
3.8GiB / 4GiB
说明:
已经接近危险值。
建议:
| 使用情况 | 判断 |
|---|---|
| <60% | 正常 |
| 60%-80% | 观察 |
| 80%-90% | 风险 |
| >90% | 容易OOM |
十一、Java容器推荐配置示例
Docker限制
--memory=4g
--memory-swap=4g
JVM
推荐:
-Xms1024m
-Xmx2048m
-XX:+UseContainerSupport
-XX:+ExitOnOutOfMemoryError
-XX:MaxMetaspaceSize=384m
-XX:MaxDirectMemorySize=512m
内存预算:
Heap 2G
Metaspace 384M
Direct 512M
Native 300~600M
总计约3.2G~3.5G
4G容器安全
十二、常见错误配置
错误1
容器:
--memory=2g
JVM:
-Xmx2048m
问题:
Heap已经接近容器上限。
其它内存没有空间。
错误2
-Xms2304m
-Xmx2048m
错误:
Xms必须 <= Xmx
正确:
-Xms1024m
-Xmx2048m
错误3
Docker启动参数传递JVM参数
错误:
docker run xxx \
--add-opens=java.base/java.lang=ALL-UNNAMED
因为:
ENTRYPOINT已经启动:
java -jar app.jar
后面的参数会作为Spring Boot参数。
JVM参数应该放:
Dockerfile ENTRYPOINT。
十三、排查顺序总结
遇到容器自动重启:
按照顺序:
1. docker ps
|
v
确认Up时间异常
2. docker inspect
|
v
查看RestartCount
3. docker inspect State
|
v
查看ExitCode
4. docker events
|
v
确认OOM / die
5. docker logs
|
v
查看Java异常
6. docker stats
|
v
观察实时内存
7. 检查JVM参数
|
v
调整-Xmx、Metaspace、DirectMemory
8. 检查代码是否存在内存泄漏
十四、关键判断口诀
ExitCode 137
+
docker events出现oom
=
内存杀进程
OOMKilled=false
不要急着否定OOM
优先相信:
docker events
十五、本次问题总结
问题原因:
容器限制:
2GB
JVM:
-Xmx2048m
+
Metaspace 400M
+
DirectMemory 1024M
实际需求:
超过3GB
结果:
OOM Killer杀死Java
exitCode=137
Docker restart自动恢复
解决:
容器:
2G → 4G
降低DirectMemory:
1024M → 512M
合理控制Heap:
-Xmx2048m
删除重复JVM参数
更多推荐
所有评论(0)