Docker如何在不调用命令外壳的情况下运行命令? [英] How does Docker run a command without invoking a command shell?

查看:72
本文介绍了Docker如何在不调用命令外壳的情况下运行命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此刻,我正在学习Docker,并通过 Dockerfile引用,特别是 RUN 指令。 RUN 有两种形式-在外壳程序中运行命令的 shell 形式和 > exec 形式,不调用命令外壳(引自 Note 部分)。

I'm learning about Docker at the moment, and going through the Dockerfile reference, specifically the RUN instruction. There are two forms of RUN - the shell form, which runs the command in a shell, and the exec form, which "does not invoke a command shell" (quoted from the Note section).

如果我理解文档正确,我的问题是-如果并且如何,Docker在没有外壳的情况下运行命令?

If I understood the documentation correctly, my question is - If, and how can, Docker run a command without a shell?


请注意,的答案可以在没有外壳的情况下执行命令实际上并不能回答问题。

Note that the answers to Can a command be executed without a shell?'s don't actually answer the question.


推荐答案

如果我正确理解您的问题后,您问的是如何在不调用命令外壳的情况下运行某些东西(特别是在Docker上下文中)。

If I understand your question correctly, you're asking how something can be run (specifically in the context of docker) without invoking a command shell.

在linux内核通常使用 exec 系列系统调用。

The way things are run in the linux kernel are usually using the exec family of system calls.

您向其传递要运行的可执行文件的路径和参数例如,需要通过execl调用传递给它。

You pass it the path to the executable you want to run and the arguments that need to be passed to it via an execl call for example.

这实际上是您的shell(sh,bash ,ksh,zsh)在后台进行操作。如果运行类似 strace -f bash -c cat / tmp / foo

This is actually what your shell (sh, bash, ksh, zsh) does under the hood anyway. You can observe this yourself if you run something like strace -f bash -c "cat /tmp/foo"

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

In the output of that command you'll see something like this:

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

真正发生的是bash在 $ PATH 中查找 cat ,然后发现 cat 实际上是一个可执行二进制文件,可从 / bin / cat 获得。然后,它只需通过 execve 调用它。以及上面显示的正确参数。

What's really going on is that bash looks up cat in $PATH, it then finds that cat is actually an executable binary available at /bin/cat. It then simply invokes it via execve. and the correct arguments as you can see above.

您可以轻松地编写一个执行相同功能的C程序。
这就是这样的程序:

You can trivially write a C program that does the same thing as well. This is what such a program would look like:

#include<unistd.h>

int main() {

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

    return 0;
}

每种语言都提供了自己的与这些系统调用的接口。 C也可以,Python也可以,而Go(大多数情况下用于编写Docker)也可以。当您按下 docker时,泊坞窗中的 RUN 指令可能会转换为这些 exec 调用之一构建。您可以运行 strace -f docker build ,然后运行 grep 执行 exec 调用日志以查看魔术的发生方式。

Every language provides its own way of interfacing with these system calls. C does, Python does and Go, which is what's used to write Docker for the most part, does as well. A RUN instruction in the docker likely translates to one of these exec calls when you hit docker build. You can run an strace -f docker build and then grep for exec calls in the log to see how the magic happens.

通过外壳运行某些内容与直接就是您失去了Shell为您做的所有花哨的工作,例如变量扩展,可执行文件搜索等。

The only difference between running something via a shell and directly is that you lose out on all the fancy stuff your shell will do for you, such as variable expansion, executable searching etc.

这篇关于Docker如何在不调用命令外壳的情况下运行命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆