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

时间:2017-02-15 18:34:08

标签: shell docker dockerfile

我正在学习Docker,并通过Dockerfile reference,特别是RUN指令。有两种形式的 RUN - shell 形式,它在shell中运行命令,以及 exec 形式, “不调用命令shell”(引自 Note 部分)。

如果我理解正确的文档,我的问题是 - 如果,如何,如何,Docker运行没有shell的命令?

  

请注意,Can a command be executed without a shell?的答案实际上并没有回答这个问题。

3 个答案:

答案 0 :(得分:5)

如果我正确地理解了你的问题,你就可以在不调用命令shell的情况下询问如何运行某些东西(特别是在docker的上下文中)。

在Linux内核中运行的方式通常是使用the exec family of system calls.

您将要传输的可执行文件的路径以及需要通过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<unistd.h>

int main() {

    execl("/bin/cat", "/bin/cat", "/tmp/foo", (char *)NULL);

    return 0;
}

每种语言都提供了与这些系统调用接口的自己的方式。 C确实如此,Python和Go,这是用来编写Docker的大部分内容,也是如此。当您点击RUN时,泊坞窗中的exec指令可能会转换为其中一个docker build来电。您可以在日志中为strace -f docker build次呼叫运行grep然后再exec来查看魔术是如何发生的。

通过shell运行某些东西与直接运行之间的唯一区别就是你失去了shell为你做的所有花哨的东西,比如变量扩展,可执行搜索等。

答案 1 :(得分:1)

程序可以在没有shell的情况下执行另一个程序;您只需创建一个新进程并在其上加载可执行文件,因此您不需要shell。用户启动程序需要shell,因为它是系统的用户界面。此外,程序无法在没有shell的情况下运行内置命令(如cd或rm),因为没有可执行的可执行文件(有其他方法可以考虑,但不是那么简单)。

答案 2 :(得分:0)

非常一般 - docker run将使用其默认进程启动容器,当docker exec允许您在容器内运行任何进程时。

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

但您可以通过运行docker exec -i my_container cmd

来运行cmd

See this answer for more details.