作者:蒋雨儿_824 | 来源:互联网 | 2023-02-11 18:14
目前,我正在学习Docker,并阅读Dockerfile参考,特别是RUN
指令。有两种形式-shell形式(RUN
在外壳中运行命令)和exec形式(“不调用命令外壳”)(从“ 注释”部分引用)。
如果我正确理解了文档,那么我的问题是-Docker是否以及如何在没有外壳的情况下运行命令?
请注意,是否可以在没有外壳的情况下执行命令?实际上并没有回答这个问题。
ffledgling..
8
如果我正确理解了您的问题,那么您正在询问如何在不调用命令外壳的情况下运行某些东西(特别是在Docker上下文中)。
事情这样在内核通常使用在Linux上运行的exec
系统调用的家庭。
例如,您将其传递到要运行的可执行文件的路径以及需要通过execl调用传递给它的参数。
无论如何,这实际上是您的shell(sh,bash,ksh,zsh)执行的操作。如果运行类似的命令,您可以自己观察strace -f bash -c "cat /tmp/foo"
在该命令的输出中,您将看到以下内容:
execve("/bin/cat", ["cat", "/tmp/foo"], [/* 66 vars */]) = 0
到底发生了什么的是bash的查找cat
中$PATH
,它则认定,cat
实际上是一个可执行的二进制提供/bin/cat
。然后,它仅通过调用它execve
。以及如上所示的正确参数。
您可以简单地编写一个执行相同功能的C程序。这样的程序看起来像这样:
#include
int main() {
execl("/bin/cat", "/bin/cat", "/tmp/foo", (char *)NULL);
return 0;
}
每种语言都提供了自己的与这些系统调用交互的方式。C做到了,Python做到了,而Go(也就是大多数情况下用来编写Docker的Go)也可以做到。当您点击时RUN
,泊坞窗中的一条指令可能会转换为这些exec
调用之一docker build
。您可以运行strace -f docker build
,然后grep
用于exec
在日志中调用,看看神奇的是如何发生的。
通过外壳运行与直接运行外壳之间的唯一区别是,您会失去外壳将为您完成的所有奇特的东西,例如变量扩展,可执行文件搜索等。
1> ffledgling..:
如果我正确理解了您的问题,那么您正在询问如何在不调用命令外壳的情况下运行某些东西(特别是在Docker上下文中)。
事情这样在内核通常使用在Linux上运行的exec
系统调用的家庭。
例如,您将其传递到要运行的可执行文件的路径以及需要通过execl调用传递给它的参数。
无论如何,这实际上是您的shell(sh,bash,ksh,zsh)执行的操作。如果运行类似的命令,您可以自己观察strace -f bash -c "cat /tmp/foo"
在该命令的输出中,您将看到以下内容:
execve("/bin/cat", ["cat", "/tmp/foo"], [/* 66 vars */]) = 0
到底发生了什么的是bash的查找cat
中$PATH
,它则认定,cat
实际上是一个可执行的二进制提供/bin/cat
。然后,它仅通过调用它execve
。以及如上所示的正确参数。
您可以简单地编写一个执行相同功能的C程序。这样的程序看起来像这样:
#include
int main() {
execl("/bin/cat", "/bin/cat", "/tmp/foo", (char *)NULL);
return 0;
}
每种语言都提供了自己的与这些系统调用交互的方式。C做到了,Python做到了,而Go(也就是大多数情况下用来编写Docker的Go)也可以做到。当您点击时RUN
,泊坞窗中的一条指令可能会转换为这些exec
调用之一docker build
。您可以运行strace -f docker build
,然后grep
用于exec
在日志中调用,看看神奇的是如何发生的。
通过外壳运行与直接运行外壳之间的唯一区别是,您会失去外壳将为您完成的所有奇特的东西,例如变量扩展,可执行文件搜索等。