SHELL ["executable", "parameters"]
SHELL指令被用于覆盖shell形式的命令的默认shell。在Linux上的默认shell是["/bin/sh", "-c"], 在windows上是["cmd", "/S", "/C"]。在Dockerfile中SHELL指令必须是JSON形式。
SHELL指令在Windows上特别有用,windows有两个常用的但是完全不同的原生shell:cmd和powershell,以及包括一个备用的sh。
SHELL指令可以出现多次。每一个SHELL指令可以覆盖先前的SHELL指令,并影响后续的指令。例如:
FROM microsoft/windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello
当RUN,CMD和ENTRYPOINT指令使用shell形式的命令时,都会受到SHELL指令的影响。
以下示例是Windows上常见的查找模式,可以通过使用SHELL指令进行简化:
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
被docker调用的命令执行时将是下面这个样子:
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
上面这种方式并不高效,原因有两个:
这里有一个不必要的cmd.exe命令处理器(aka shell)被调用。
每一个shell形式的RUN指令需要一个额外的powershell -command作为命令前缀。
为了提高效率,可以采用两种机制之一。一种是使用RUN命令的JSON形式,如:
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
虽然JSON形式比较清晰,不会使用不必要的cmd.exe,但通过双引号和转义使得写法非常啰嗦。替代方案是使用SHELL指令和shell形式,为Windows用户创建一种更自然的语法,特别与解析器指令结合使用时:
# escape=`
FROM microsoft/nanoserver
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'
运行结果:
PS E:\docker\build\shell> docker build -t shell .
Sending build context to Docker daemon 4.096 kB
Step 1/5 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/5 : SHELL powershell -command
---> Running in 6fcdb6855ae2
---> 6331462d4300
Removing intermediate container 6fcdb6855ae2
Step 3/5 : RUN New-Item -ItemType Directory C:\Example
---> Running in d0eef8386e97
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/28/2016 11:26 AM Example
---> 3f2fbf1395d9
Removing intermediate container d0eef8386e97
Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\
---> a955b2621c31
Removing intermediate container b825593d39fc
Step 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world'
---> Running in be6d8e63fe75
hello world
---> 8e559e9bf424
Removing intermediate container be6d8e63fe75
Successfully built 8e559e9bf424
PS E:\docker\build\shell>
SHELL指令也可以被用于修改shell的操作。例如,在windows上使用SHELL CMD /S /C /V:ON|OFF可以修改延迟环境变量扩展语义。
SHELL特性在Docker1.12被添加。