以下内容翻译自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.