Linux入门教程:Dockerfile参考(18) – SHELL设置执行命令的shell,运行命令Linux的默认sh


格式:

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:\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>

Docker 1.12开始添加了此SHELL功能。

相关内容