SHELL
SHELL ["executable", "parameters"]
SHELL
指令可以覆盖操作系统中默认的shell。在Linux中默认的shell是["/bin/sh", "-c"]
,在Windows中是["cmd", "/S", "/C"]
。在Dockerfile当中SHELL
指令必须被写作JSON形式。
在Windows操作系统中,SHELL
指令是相当有用的,因为在Windows当中有两个经常使用的shell:cmd
和powershell
,包括可选的shellsh
。
SHELL
指令可以出现多次。每个SHELL
指令会覆盖前一个SHELL
指令,并且会影响后续的所有指令。例如:
FROM microsoft/windowsservercore
# 在 cmd /S /C 执行 echo default
RUN echo default
# 在 cmd /S /C powershell -command 执行 Write-Host default
RUN powershell -command Write-Host default
# 在 powershell -command 执行 Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# 在 cmd /S /C 执行 echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello
在Dockerfile当中,shell形式的RUN
,CMD
和ENTRYPOINT
指令会被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 -command
去预处理这个指令。
为了使这个更有效率,有两种方法可以采用。一种是使用JSON形式的RUN指令:
...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...
JSON形式是清楚的,并且没有使用不需要的cmd.exe,不过他会需要更冗长的引号和转义符。代替的方法是使用SHELL
命令和shell形式。使Windows用户使用会更加自然,特别是遇到escape
解析的时候:
# 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
指令同样可以用在Linux当中,修改shell为被需要的如zsh
,csh
,tcsh
等。
SHELL
功能在Docker 1.12中添加。