Dockerfile中shell和exec形式的说明

449 阅读2分钟

以下内容翻译自docker官方文档,谨此作为学习记录,方便以后查阅,分享给大家。

shell和exec形式

RUN, CMD, 和 ENTRYPOINT 指令均支持shell和exec这两种形式的写法,如下:

INSTRUCTION ["executable","param1","param2"] (exec 形式)

INSTRUCTION command param1 param2 (shell 形式)

exec形式可以避免shell字符串修改,并且可以使用特定的shell命令或任何其他可执行程序。该形式使用JSON数组语法,其中数组中的每个元素是一个命令、标志或参数。

shell形式更加轻松,强调易用性、灵活性和可读性。shell形式会自动使用命令shell,而exec形式则不会,怎么理解这句话呢,其实就是shell形式下,默认设置下会在最前面加上/bin/sh -c最后实际执行的是/bin/sh -c command param1 param2如:CMD /bin/ls -al /  等价于 CMD ["/bin/sh","-c","/bin/ls -al /"],因为 default shell on Linux is ["/bin/sh", "-c"]

Exec形式

exec形式被解析成JSON数组,因此只能使用双引号,不能使用单引号,如下

ENTRYPOINT ["/bin/bash", "-c", "echo", "hello"]

exec形式最适合用于指定ENTRYPOINT指令,并与CMD结合使用,用于设置可在运行时覆盖的默认参数。

变量替换

使用exec形式不会自动调用命令shell,也就是说正常的shell处理(例如变量替换)不会发生。例如,RUN ["echo", "$HOME"] 不会处理$HOME的变量替换。

如果您想要shell处理,那么要么使用shell形式,要么直接使用exec形式执行shell,例如,RUN ["sh", "-c", "echo $HOME" ]。当使用exec形式并直接执行shell时(正如shell形式的情况一样),因为执行环境变量替换的是shell,而不是构建器。

反斜杠

在exec形式中,必须转义反斜杠。这在使用反斜杠作为路径分隔符的Windows上尤其重要。由于不是有效的JSON,以下行将被视为shell形式,并以意想不到的方式失败:

RUN ["c:\windows\system32\tasklist.exe"]

这个例子的正确写法应该是:

RUN ["c:\windows\system32\tasklist.exe"]

Shell形式

与exec形式不同,使用shell形式的指令总是使用命令shell。shell形式不使用JSON数组格式,而是一个常规字符串。shell形式字符串允许使用转义字符(默认情况下为反斜杠)转义换行,从而将单个指令延续到下一行。因此对于较长的命令在shell形式下可以通过""将其分成多行。例如:

RUN source $HOME/.bashrc && \
echo $HOME

等价于:

RUN source $HOME/.bashrc && echo $HOME

也可以在shell形式中使用heredocs来分解命令,如下:

RUN <<EOF
source $HOME/.bashrc && \
echo $HOME
EOF

有关heredocs的更多信息, 查看 Here-documents.

使用不同的shell

通过SHELL命令来改变默认的shell,如下,将默认shell /bin/sh -c 改成 /bin/bash -c

SHELL ["/bin/bash", "-c"]
RUN echo hello

更多信息, 查看 SHELL.