殼指令
placeholderCopySHELL ["executable", "parameters"]
SHELL
指令允許覆蓋用於 shell 形式命令的預設 shell。Linux 上的預設 shell 是 ["/bin/sh", "-c"]
,而 Windows 上的預設 shell 是 ["cmd", "/S", "/C"]
。必須在 Dockerfile 中以 JSON 格式編寫 SHELL
指令。
SHELL
指令在 Windows 上特別有用,其中有兩個常用且完全不同的本機 shell:cmd 和 powershell,以及包括 sh 的備用 shell。
SHELL
指令可以多次出現。每個 SHELL
指令都會覆蓋所有先前的 SHELL
指令,並影響所有後續指令。例如:
placeholderCopyFROM 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
指令的 shell 形式用於 Dockerfile 時,以下說明會受到影響:RUN
,CMD
和 ENTRYPOINT
。
以下示例是在 Windows 上找到的常見模式,可以使用 SHELL
指令簡化:
placeholderCopy...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...
docker 呼叫的命令將是:
placeholderCopycmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
由於兩個原因,這是低效的。首先,呼叫一個不必要的 cmd.exe 命令處理器(也就是 shell)。其次,shell 形式的每個 RUN
指令都需要一個額外的 powershell -command 字首命令。
為了提高效率,可以採用兩種機制中的一種。一種是使用 RUN
命令的 JSON 形式,例如:
placeholderCopy...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...
雖然 JSON 表單是明確的,並且不使用不必要的 cmd.exe,但它確實需要通過雙引號和轉義更加詳細。替代機制是使用 SHELL
指令和 shell 表單,為 Windows 使用者建立更自然的語法,特別是與 escape parser 指令結合使用時:
placeholderCopy# 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'
導致:
placeholderCopyPS 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 的執行方式。例如,在 Windows 上使用 SHELL cmd /S /C /V:ON|OFF
,可以修改延遲的環境變數擴充套件語義。
如果需要備用 shell,如 zsh,csh,tcsh 等,也可以在 Linux 上使用 SHELL
指令。
在 Docker 1.12 中新增了 SHELL
功能。