问题描述
有时候你需要调查一个已停止的容器,或者一个在启动后很快失败并停止的容器。使用 docker exec -ti <id> bash
命令只能在运行中的容器上使用,一旦它完成,bash 提示符也会终止。使用 docker start
命令不能提供一个不同的命令,如果容器再次突然停止,你将没有足够的时间进入容器进行调查。你可以使用 docker commit
,然后使用新镜像上的 docker run
命令来运行不同的命令,但我想知道是否还有其他选择。需要注意的是,docker logs
只会返回应用程序打印到 stdout/stderr 的内容,这可能不足以找出问题所在。
解决方案
请注意以下操作可能存在版本差异及风险,请在实际操作前谨慎备份。
使用 strace
跟踪进程失败原因
一种常用的方法是在Linux中使用 strace
跟踪进程的系统调用,这通常会指出进程失败的原因。你可以创建一个名为 Dockerfile
的文件,内容如下:
FROM original_image
RUN apt-get -y update && apt-get install -y strace
使用 docker build -t debug_version
命令构建新的镜像,然后使用 docker run debug_version strace original_cmd
命令运行你的新镜像,其中 original_cmd
是原始容器中的命令。对于那些会 fork 子进程然后退出的进程,你可以使用 strace
的 -ff
选项来运行。你还可以使用 Docker 数据卷来映射一些文件,并使用 strace
的 -o
选项将输出写入其中。一般情况下,strace
会将输出留在 stdout 中,可以使用 docker log
来查看。
修改容器入口命令
如果容器在启动时立即失败,你可以使用 docker run
命令来指定替代的 --entrypoint
和 CMD
。通常,我会将其设置为一个不会自行退出的循环或类似的内容。一旦进入容器,你可以手动运行失败的步骤,然后在容器不退出的情况下检查结果。
其他注意事项
请注意,尽管你可以使用上述方法来调查进程失败的原因,但在一些情况下,容器的日志和输出可能不足以解决问题。在处理容器问题时,确保你了解应用程序的行为,可能需要根据具体情况进行调整和扩展。
总结
无论是使用 strace
跟踪系统调用,还是修改容器入口命令,都可以帮助你调查容器中主进程失败的原因。通过这些方法,你可以更好地理解进程失败的原因,并采取适当的措施来解决问题。在处理容器问题时,要特别注意容器的日志和输出,以及应用程序本身的行为。