如何获取Docker容器中Go入口进程的Goroutine Dump?
解决容器内Go进程Goroutine Dump无法获取的问题
以下是几种可行的方案,按推荐优先级排序:
1. 集成pprof HTTP接口(最稳妥)
在Go程序中添加pprof支持,无需发送QUIT信号即可获取dump,进程不会终止:
- 在代码中导入pprof包并启动HTTP服务:
import _ "net/http/pprof" import "log" import "net/http" func main() { // 启动pprof监听,端口可自定义 go func() { if err := http.ListenAndServe("0.0.0.0:6060", nil); err != nil { log.Printf("pprof server failed: %v", err) } }() // 你的业务逻辑代码 } - 确保docker-compose配置中容器的6060端口(或自定义端口)未被限制,然后在宿主机执行:
直接获取完整的Goroutine Dump内容,进程和容器都不会停止。docker exec <container-id> curl http://localhost:6060/debug/pprof/goroutine?debug=2
2. 重定向Go进程的stderr到文件
启动Go程序时,将标准错误输出重定向到容器内的持久化文件,这样即使进程终止,文件依然存在:
- 修改docker-compose中Go服务的启动命令,比如:
services: go-app: command: ./your-go-binary 2>/app/goroutine_dump.log # 其他配置... - 当需要获取dump时,进入容器发送QUIT信号:
docker exec -it <container-id> kill -QUIT <pid> - 即使容器停止,也可以通过docker cp将文件拷出:
docker cp <container-id>:/app/goroutine_dump.log ./local_dump.log
3. 通过docker logs捕获dump
如果Go进程的stderr默认输出到容器日志(大部分情况都是如此),发送QUIT信号后,dump会被写入容器日志,即使容器停止也能读取:
- 发送QUIT信号:
docker exec <container-id> kill -QUIT <pid> - 容器停止后,执行以下命令查看并提取日志中的dump:
docker logs <container-id> | grep -A 1000 "goroutine stack traces:"
4. 实时捕获dump输出
无需进入容器,直接通过docker exec组合命令发送信号并立即捕获输出:
docker exec <container-id> sh -c 'kill -QUIT <pid>; sleep 0.5; cat /proc/<pid>/fd/2'
注:这个方法依赖进程在退出前能将dump写入stderr,若进程退出过快可能失效,建议优先用前三种方法。
内容的提问来源于stack exchange,提问作者TieDad
相关产品推荐
相关产品推荐

