格式:
- SHELL ["executable", "parameters"]
SHELL指令可以覆盖命令的shell模式所使用的默认shell。Linux的默认shell是[“/bin/sh”, “-c”],Windows的是[“cmd”, “/S”, “/C”]。SHELL指令必须以JSON格式编写。
SHELL指令在有两个常用的且不太相同的本地shell:cmd和powershell,以及可选的sh的windows上特别有用。
SHELL指令可以出现多次。每个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
当RUN, CMD和ENTRYPOINT使用shell形式时,将使用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。第二,每个使用shell模式的RUN指令需要一个额外的powershell。
为了优化这个命令更有效率,有两个方法,其中之一使用RUN指令的JSON形式,如:
- …
- RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 "c:\foo.txt""]
- …
虽然没有调用了cmd.exe,不过需要对双引号进行转义,看起来比较冗长。另一种机制是使用SHELL指令和shell形式,使得windows用户可以使用更自然的语法,特别是与escape指令一起用时:
- # escape=`
- FROM windowsservercore
- SHELL ["powershell","-command"]
- RUN New-Item -ItemType Directory C:Example
- ADD Execute-MyCmdlet.ps1 c:example
- RUN c:exampleExecute-MyCmdlet -sample ‘hello world’
构建结果为:
- PS E:dockerbuildshell> 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:exampleExecute-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:dockerbuildshell>
Docker 1.12开始添加了此SHELL功能。