1. 程式人生 > 實用技巧 >【Docker】Dockerfile 之 SHELL

【Docker】Dockerfile 之 SHELL

參考教程:https://docs.docker.com/engine/reference/builder/

環境

  1. virtual box 6.1
  2. centos 7.8
  3. docker 19.03

SHELL

SHELL ["executable", "parameters"]

The SHELL instruction allows the default shell used for the shell form of commands to be overridden. The default shell on Linux is ["/bin/sh", "-c"], and on Windows is ["cmd", "/S", "/C"]

. The SHELL instruction must be written in JSON form in a Dockerfile.

SHELL 指令允許覆蓋用於 shell 形式的命令的預設 shell。在 Linux 上,預設 shell 是 ["/bin/sh", "-c"],而在 Windows 上,預設 shell 是 ["cmd", "/S", "/C"]SHELL 指令必須以 JSON 格式寫入 Dockerfile 中。

The SHELL instruction is particularly useful on Windows where there are two commonly used and quite different native shells: cmd

and powershell, as well as alternate shells available including sh.

SHELL 指令在 Windows 上特別有用,在 Windows 上有兩個常用且完全不同的本機shell:cmdpowershell,以及可用的替代 shell,包括 sh

The SHELL instruction can appear multiple times. Each SHELL instruction overrides all previous SHELL instructions, and affects all subsequent instructions. For example:

SHELL 指令可以出現多次。每條 SHELL 指令都將覆蓋所有先前的 SHELL 指令,並影響所有後續指令。例如:

FROM microsoft/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

The following instructions can be affected by the SHELL instruction when the shell form of them is used in a Dockerfile: RUN, CMD and ENTRYPOINT.

當它們的 shell 形式在 Dockerfile 中使用時,以下指令可能會受到 SHELL 指令的影響:RUNCMDENTRYPOINT

The following example is a common pattern found on Windows which can be streamlined by using the SHELL instruction:

以下示例是 Windows 上常見的模式,可以通過使用 SHELL 指令進行精簡:

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

The command invoked by docker will be:
docker 呼叫的命令將是:

cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"

This is inefficient for two reasons. First, there is an un-necessary cmd.exe command processor (aka shell) being invoked. Second, each RUN instruction in the shell form requires an extra powershell -command prefixing the command.

這效率低下有兩個原因。首先,有一個不必要的 cmd.exe 命令處理器(也稱為 shell)被呼叫。其次,shell 格式的每條 RUN 指令都需要在命令前面加上一個額外的 powershell -command

To make this more efficient, one of two mechanisms can be employed. One is to use the JSON form of the RUN command such as:

為了使其更有效,可以採用兩種機制之一。一種是使用 RUN 命令的 JSON 形式,例如:

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

While the JSON form is unambiguous and does not use the un-necessary cmd.exe, it does require more verbosity through double-quoting and escaping. The alternate mechanism is to use the SHELL instruction and the shell form, making a more natural syntax for Windows users, especially when combined with the escape parser directive:

儘管 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'

Resulting in:

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>

The SHELL instruction could also be used to modify the way in which a shell operates. For example, using SHELL cmd /S /C /V:ON|OFF on Windows, delayed environment variable expansion semantics could be modified.

SHELL 指令還可用於修改外殼的執行方式。例如,在 Windows 上使用 SHELL cmd /S /C /V:ON|OFF,可以修改延遲的環境變數擴充套件語義。

The SHELL instruction can also be used on Linux should an alternate shell be required such as zsh, csh, tcsh and others.

如果需要備用外殼,例如 zshcshtcsh等,也可以在 Linux 上使用 SHELL 指令。

總結

介紹了 Dockerfile 中 SHELL 指令的用法和注意事項。