Docker SHELL 指令

示例

SHELL ["executable", "parameters"]

该SHELL指令允许覆盖用于命令的shell形式的默认shell。在Linux上["/bin/sh", "-c"],默认shell是,在Windows上,默认shell是["cmd", "/S", "/C"]。该SHELL指令必须在Dockerfile中以JSON形式编写。

该SHELL指令在Windows上特别有用,在Windows上有两个常用且完全不同的本机外壳:cmd和powershell,以及可用的备用外壳,包括sh。

该SHELL说明可以出现多次。每个SHELL指令将覆盖所有先前的SHELL指令,并影响所有后续的指令。例如:

FROM 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

以下说明可通过受影响SHELL的指令时,其中的外壳形式在Dockerfile使用:RUN,CMD和ENTRYPOINT。

以下示例是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命令处理器(又名shell)被调用。其次,RUNshell形式的每条指令都需要一个额外的powershell -command作为命令的前缀。

为了使其更有效,可以采用两种机制之一。一种是使用RUN命令的JSON形式,例如:

...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...

尽管JSON形式是明确的,并且不使用不必要的cmd.exe,但它确实需要通过双引号和转义来实现更多的详细信息。另一种机制是使用SHELL指令和外壳程序形式,使Windows用户的语法更自然,尤其是与转义解析器指令结合使用时:

# escape=`

FROM windowsservercore
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 3.584 kB
Step 1 : FROM windowsservercore
 ---> 5bc36a335344
Step 2 : SHELL powershell -command
 ---> Running in 87d7a64c9751
 ---> 4327358436c1
Removing intermediate container 87d7a64c9751
Step 3 : RUN New-Item -ItemType Directory C:\Example
 ---> Running in 3e6ba16b8df9


Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         6/2/2016   2:59 PM                Example


 ---> 1f1dfdcec085
Removing intermediate container 3e6ba16b8df9
Step 4 : ADD Execute-MyCmdlet.ps1 c:\example\
 ---> 6770b4c17f29
Removing intermediate container b139e34291dc
Step 5 : RUN c:\example\Execute-MyCmdlet -sample 'hello world'
 ---> Running in abdcf50dfd1f
Hello from Execute-MyCmdlet.ps1 - passed hello world
 ---> ba0e25255fda
Removing intermediate container abdcf50dfd1f
Successfully built ba0e25255fda
PS E:\docker\build\shell>

该SHELL指令还可用于修改外壳的操作方式。例如,SHELL cmd /S /C /V:ON|OFF在Windows上使用,可以修改延迟的环境变量扩展语义。

如果SHELL需要备用外壳,例如zsh,csh,tcsh等,该指令也可以在Linux上使用。

该SHELL功能已在Docker 1.12中添加。