一、背景
平时用的镜像是:
eclipse-temurin:8-jre-focal- 优点:小、稳定、适合生产
- 缺点:没有
jmap/jstack/jps/jinfo等工具 - 也就是说,如果 JVM 出问题(死锁、内存泄漏、线程堵塞),你无法用这些经典工具排查
二、解决方案:临时挂载 JDK 容器排查
1️⃣ 核心思路
Docker 容器里有一个 PID namespace(进程空间)概念:
- 每个容器进程都有自己的 PID namespace
- 默认情况下,一个容器看不到另一个容器里的进程
- 可以通过
--pid=container:<容器ID>来共享进程空间
所以,你可以:
- 业务容器运行 JRE(轻量)
- 起一个新的 临时 JDK 容器
- 通过
--pid=container:<业务容器ID>让这个临时容器看到业务容器里的 Java 进程 - 在 JDK 容器里用
jmap/jstack等工具直接操作业务容器里的 JVM
2️⃣ 举个例子
假设你业务容器叫 app,运行 JRE:
docker run -d --name app eclipse-temurin:8-jre-focal java -jar /app/app.jar- 业务正常运行,JRE 就够
- 发生问题,例如死锁或内存泄漏
你可以临时起一个 JDK 容器:
docker run -it --rm \
--pid=container:app \
openjdk:8u322-jdk-bullseye bash然后在这个容器里:
# 查看 JVM 进程
jps -l
# dump 堆
jmap -dump:format=b,file=/tmp/heap.bin <pid>
# 打印线程
jstack <pid>这样,你不用在生产容器里安装完整 JDK,也能做排查。
3️⃣ 优点
- 生产容器保持轻量(JRE)
- 不暴露 JDK 工具(安全性高)
- 排查灵活,问题发生时才临时挂载
- 完全可自动化(CI/CD + K8s debug 流程)
4️⃣ 注意事项
- 临时 JDK 容器最好和业务容器同一台宿主机,否则 PID 不共享
- 堆 dump / jstack 文件要注意存储位置
- 排查结束后,临时容器销毁,不留痕迹
💡 一句话总结
平时轻量运行 JRE,出问题用临时 JDK 容器挂载 PID namespace 来排查
这就是生产环境安全、轻量又可排障的标准做法。
作者:张三 创建时间:2026-02-02 20:30
最后编辑:张三 更新时间:2026-02-02 20:30
最后编辑:张三 更新时间:2026-02-02 20:30