day*_*oli 4 shell docker dockerfile
目前,我正在学习Docker,并阅读Dockerfile参考,特别是RUN指令。有两种形式-shell形式(RUN在外壳中运行命令)和exec形式(“不调用命令外壳”)(从“ 注释”部分引用)。
如果我正确理解了文档,那么我的问题是-Docker是否以及如何在没有外壳的情况下运行命令?
请注意,是否可以在没有外壳的情况下执行命令?实际上并没有回答这个问题。
如果我正确理解了您的问题,那么您正在询问如何在不调用命令外壳的情况下运行某些东西(特别是在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
Run Code Online (Sandbox Code Playgroud)
到底发生了什么的是bash的查找cat中$PATH,它则认定,cat实际上是一个可执行的二进制提供/bin/cat。然后,它仅通过调用它execve。以及如上所示的正确参数。
您可以简单地编写一个执行相同功能的C程序。这样的程序看起来像这样:
#include<unistd.h>
int main() {
execl("/bin/cat", "/bin/cat", "/tmp/foo", (char *)NULL);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
每种语言都提供了自己的与这些系统调用交互的方式。C做到了,Python做到了,而Go(也就是大多数情况下用来编写Docker的Go)也可以做到。当您点击时RUN,泊坞窗中的一条指令可能会转换为这些exec调用之一docker build。您可以运行strace -f docker build,然后grep用于exec在日志中调用,看看神奇的是如何发生的。
通过外壳运行与直接运行外壳之间的唯一区别是,您会失去外壳将为您完成的所有奇特的东西,例如变量扩展,可执行文件搜索等。