搜索上面的内容可以看到很多关于如何为在docker容器中运行的应用设置断点的结果,但我对在Dockerfile
* 本身 * 中设置断点感兴趣,这样docker build
就在断点处暂停。例如Dockerfile
:
FROM ubuntu:20.04
RUN echo "hello"
RUN echo "bye"
我正在寻找一种在RUN echo "bye"
上设置断点的方法,这样当我调试这个Dockerfile
时,映像将以非交互方式构建到RUN echo "bye"
点,独占。之后,我将能够与容器交互地运行命令。在我拥有的实际Dockerfile
中,在断点之前有RUN
,它们会更改正在构建的映像的文件系统,我希望能够在断点处交互式地运行cd
/ls
/find
等命令,从而分析断点处映像的文件系统。
5条答案
按热度按时间rn0zuynd1#
您不能设置断点 * 本身 *,但是您可以在构建序列中的任意点(步骤之间)获得交互式shell。
让我们建立你的形象:
每一行写有十六进制ID的
---> 0123456789ab
都有一个有效的图像ID。所以从这里你可以这将在第一个
RUN
命令生成的部分图像上给予一个交互式shell。不要求构建作为一个整体成功。如果
RUN
步骤失败,您可以使用此技术在该步骤之前立即在映像上获取交互式shell,然后手动重新运行命令。如果您有一个很长的RUN
命令,您可能需要将它分成两个,以便能够在命令序列中的特定点获得调试shell。vatpfxk52#
我不认为这是可能的直接-该功能已被discussed和拒绝。
我通常在调试Dockerfile时会注解“断点”之后的所有步骤,然后运行
docker build
,然后运行docker run -it image bash
或docker run -it image sh
(取决于容器中是否安装了bash)。然后,我有一个交互式shell,我可以运行命令来调试为什么后面的阶段失败。
不过,我同意能够设置断点并四处查看将是一个方便的功能。
fd3cxomn3#
您可以使用Remote shell debugging技巧在中间容器中运行命令。
确保你的容器镜像包含基本的实用程序,如netcat(
nc
)和fuser
。这些实用程序支持从任何中间容器映像“调用home”。在家里,你可以用netcat(或socat)接听电话。这个netcat会将你的命令发送到容器,并打印它们的结果。这种调试方法甚至可以在云中某个未知工作节点上构建的Dockerfile上工作。示例:
在启动Docker构建之前,开始等待和应答来自Dockerfile * 的调用。在主主机上运行
nc -k -l -p 33720
(或者socat STDIN TCP-LISTEN:33720,reuseaddr,fork
)。这就是上面的例子在家里的样子:
mklgxw1f4#
最近(2022年5月)的项目
ktock/buildg
提供了断点。参见Kohei Tokunaga中的“Interactive debugger for Dockerfile”
buildg
是一个基于BuildKit交互调试Dockerfile的工具。命令
break
,b LINE_NUMBER
设置断点。示例:
PR 24:
添加
--cache-reuse
选项,允许在buildg debug调用之间共享构建缓存,以使第二次调试更快。这对于加快运行
buildg
多次调试出错步骤非常有用。请注意,缓存步骤上的断点从现在起被忽略。
由于此限制,此功能目前是可选的。我们应该修复这个限制,并使其成为未来的默认行为。
9gm1akwq5#
Docker让事情变得“困难”。以下是我想出的一个解决方案:
1.在需要断点的位置插入
FROM scratch
。docker build . --target=<n-1>
,其中<n>
是“断点”之前的FROM
命令数。例如,如果是单阶段构建,则使用--target=0
。FROM <image> AS <stage>
命名了想要断点的阶段,则可以使用--target=<stage>
。Docker已经缓存了所有成功的层(即使你看不到它们),并且因为
FROM
“断点”位于(可能不成功的)兴趣点之前,所以构建应该都来自缓存并且非常快。例如,如果我的
Dockerfile
看起来像这样:然后我可以像这样添加一个“断点”:
然后用
docker build . --target=build
触发