Builder default shell

Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
John Howard 2016-05-03 13:56:59 -07:00 committed by Tibor Vass
parent 7e00f19c4f
commit 0cb3440a21

View File

@ -497,7 +497,8 @@ generated images.
RUN has 2 forms: RUN has 2 forms:
- `RUN <command>` (*shell* form, the command is run in a shell - `/bin/sh -c`) - `RUN <command>` (*shell* form, the command is run in a shell, which by
default is `/bin/sh -c` on Linux or `cmd /S /C` on Windows)
- `RUN ["executable", "param1", "param2"]` (*exec* form) - `RUN ["executable", "param1", "param2"]` (*exec* form)
The `RUN` instruction will execute any commands in a new layer on top of the The `RUN` instruction will execute any commands in a new layer on top of the
@ -509,7 +510,10 @@ concepts of Docker where commits are cheap and containers can be created from
any point in an image's history, much like source control. any point in an image's history, much like source control.
The *exec* form makes it possible to avoid shell string munging, and to `RUN` The *exec* form makes it possible to avoid shell string munging, and to `RUN`
commands using a base image that does not contain `/bin/sh`. commands using a base image that does not contain the specified shell executable.
The default shell for the *shell* form can be changed using the `SHELL`
command.
In the *shell* form you can use a `\` (backslash) to continue a single In the *shell* form you can use a `\` (backslash) to continue a single
RUN instruction onto the next line. For example, consider these two lines: RUN instruction onto the next line. For example, consider these two lines:
@ -1541,6 +1545,120 @@ generated with the new status.
The `HEALTHCHECK` feature was added in Docker 1.12. The `HEALTHCHECK` feature was added in Docker 1.12.
## 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.
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`.
The `SHELL` instruction can appear multiple times. Each `SHELL` instruction overrides
all previous `SHELL` instructions, and affects all subsequent instructions. For example:
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
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`.
The following example is a common pattern found on Windows which can be
streamlined by using the `SHELL` instruction:
...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...
The command invoked by docker will be:
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.
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 ["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:
# 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'
Resulting in:
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>
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.
The `SHELL` instruction can also be used on Linux should an alternate shell be
required such `zsh`, `csh`, `tcsh` and others.
The `SHELL` feature was added in Docker 1.12.
## Dockerfile examples ## Dockerfile examples