diff --git a/docs/reference/builder.md b/docs/reference/builder.md index b9a894444b..6217d0d341 100644 --- a/docs/reference/builder.md +++ b/docs/reference/builder.md @@ -497,7 +497,8 @@ generated images. RUN has 2 forms: -- `RUN ` (*shell* form, the command is run in a shell - `/bin/sh -c`) +- `RUN ` (*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) 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. 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 RUN instruction onto the next line. For example, consider these two lines: @@ -1469,7 +1473,7 @@ For example you might add something like this: ## STOPSIGNAL - STOPSIGNAL signal + STOPSIGNAL signal The `STOPSIGNAL` instruction sets the system call signal that will be sent to the container to exit. This signal can be a valid unsigned number that matches a position in the kernel's syscall table, for instance 9, @@ -1541,6 +1545,120 @@ generated with the new status. 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