Docker如何在不调用命令行的情况下运行一个命令?

目前我正在学习Docker,并通过Dockerfile参考 ,特别是RUN指令。 有两种forms的RUN – 在shell中运行命令的shellforms,以及“不调用命令shell”(从注释部分引用)的execforms。

如果我正确理解了文档,我的问题是 – 如果Docker在没有shell的情况下运行一个命令,又该如何运行?

请注意, Can命令的答案可以在没有shell的情况下执行? 实际上并没有回答这个问题。

如果我正确地理解了你的问题,你问的是如何运行(特别是在docker的上下文中)而不用调用命令shell。

在Linux内核中运行的方式通常使用系统调用的exec系列。

您将它传递给要运行的可执行文件的path以及需要通过execl调用传递给它的参数。


这实际上是你的shell(sh,bash,ksh,zsh)在引擎盖下做的。 你可以自己观察,如果你运行像strace -f bash -c "cat /tmp/foo"

在该命令的输出中,您将看到如下所示的内容:

 execve("/bin/cat", ["cat", "/tmp/foo"], [/* 66 vars */]) = 0 

真正发生的是bash在$PATH查找cat ,然后发现cat实际上是/bin/cat可用的可执行二进制文件。 然后通过execve调用它。 和正确的参数,你可以看到上面。

你可以简单地写一个C程序来做同样的事情。 这就是这样一个程序的样子:

 #include<unistd.h> int main() { execl("/bin/cat", "/bin/cat", "/tmp/foo", (char *)NULL); return 0; } 

每种语言都提供了与这些系统调用接口的自己的方式。 C做的,Python的做和Go,这也是大部分用来编写Docker的东西。 RUN中的RUN指令可能会转化为这些exec调用中的一个。 你可以运行一个strace -f docker build ,然后在日志中调用exec调用这个魔法。


通过shell和直接运行的唯一区别在于,你可能会失去所有你的shell为你做的东西,比如variables扩展,可执行文件search等等。

程序可以在没有shell的情况下执行另一个程序 你只需创build一个新的进程并在其上加载一个可执行文件,所以你不需要shell。 用户需要shell来启动程序,因为它是系统的用户界面。 另外,一个程序不能像没有shell的cd或rm那样运行一个内置的命令,因为没有可执行文件被find(有其他的方法,想法,但并不那么简单)。

在非常普遍的情况下,当docker exec允许你在容器中运行你想要的任何进程时, docker run会启动容器的默认进程。

例如,通过docker run microsoft/iis运行microsoft / iis容器将运行默认进程,即powershell。

但是你可以通过运行docker exec -i my_container cmd来运行docker exec -i my_container cmd

看到这个答案的更多细节。