@@ -274,8 +274,8 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str
274274// RUN some command yo
275275//
276276// run a command and commit the image. Args are automatically prepended with
277- // 'sh -c' under linux or 'cmd /S /C' under Windows, in the event there is
278- // only one argument. The difference in processing:
277+ // the current SHELL which defaults to 'sh -c' under linux or 'cmd /S /C' under
278+ // Windows, in the event there is only one argument The difference in processing:
279279//
280280// RUN echo hi # sh -c echo hi (Linux)
281281// RUN echo hi # cmd /S /C echo hi (Windows)
@@ -293,13 +293,8 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
293293 args = handleJSONArgs (args , attributes )
294294
295295 if ! attributes ["json" ] {
296- if runtime .GOOS != "windows" {
297- args = append ([]string {"/bin/sh" , "-c" }, args ... )
298- } else {
299- args = append ([]string {"cmd" , "/S" , "/C" }, args ... )
300- }
296+ args = append (getShell (b .runConfig ), args ... )
301297 }
302-
303298 config := & container.Config {
304299 Cmd : strslice .StrSlice (args ),
305300 Image : b .image ,
@@ -408,11 +403,7 @@ func cmd(b *Builder, args []string, attributes map[string]bool, original string)
408403 cmdSlice := handleJSONArgs (args , attributes )
409404
410405 if ! attributes ["json" ] {
411- if runtime .GOOS != "windows" {
412- cmdSlice = append ([]string {"/bin/sh" , "-c" }, cmdSlice ... )
413- } else {
414- cmdSlice = append ([]string {"cmd" , "/S" , "/C" }, cmdSlice ... )
415- }
406+ cmdSlice = append (getShell (b .runConfig ), cmdSlice ... )
416407 }
417408
418409 b .runConfig .Cmd = strslice .StrSlice (cmdSlice )
@@ -535,8 +526,8 @@ func healthcheck(b *Builder, args []string, attributes map[string]bool, original
535526
536527// ENTRYPOINT /usr/sbin/nginx
537528//
538- // Set the entrypoint (which defaults to sh -c on linux, or cmd /S /C on Windows) to
539- // /usr/sbin/nginx. Will accept the CMD as the arguments to /usr/sbin/nginx .
529+ // Set the entrypoint to /usr/sbin/nginx. Will accept the CMD as the arguments
530+ // to /usr/sbin/nginx. Uses the default shell if not in JSON format .
540531//
541532// Handles command processing similar to CMD and RUN, only b.runConfig.Entrypoint
542533// is initialized at NewBuilder time instead of through argument parsing.
@@ -557,11 +548,7 @@ func entrypoint(b *Builder, args []string, attributes map[string]bool, original
557548 b .runConfig .Entrypoint = nil
558549 default :
559550 // ENTRYPOINT echo hi
560- if runtime .GOOS != "windows" {
561- b .runConfig .Entrypoint = strslice.StrSlice {"/bin/sh" , "-c" , parsed [0 ]}
562- } else {
563- b .runConfig .Entrypoint = strslice.StrSlice {"cmd" , "/S" , "/C" , parsed [0 ]}
564- }
551+ b .runConfig .Entrypoint = strslice .StrSlice (append (getShell (b .runConfig ), parsed [0 ]))
565552 }
566553
567554 // when setting the entrypoint if a CMD was not explicitly set then
@@ -727,6 +714,28 @@ func arg(b *Builder, args []string, attributes map[string]bool, original string)
727714 return b .commit ("" , b .runConfig .Cmd , fmt .Sprintf ("ARG %s" , arg ))
728715}
729716
717+ // SHELL powershell -command
718+ //
719+ // Set the non-default shell to use.
720+ func shell (b * Builder , args []string , attributes map [string ]bool , original string ) error {
721+ if err := b .flags .Parse (); err != nil {
722+ return err
723+ }
724+ shellSlice := handleJSONArgs (args , attributes )
725+ switch {
726+ case len (shellSlice ) == 0 :
727+ // SHELL []
728+ return errAtLeastOneArgument ("SHELL" )
729+ case attributes ["json" ]:
730+ // SHELL ["powershell", "-command"]
731+ b .runConfig .Shell = strslice .StrSlice (shellSlice )
732+ default :
733+ // SHELL powershell -command - not JSON
734+ return errNotJSON ("SHELL" , original )
735+ }
736+ return b .commit ("" , b .runConfig .Cmd , fmt .Sprintf ("SHELL %v" , shellSlice ))
737+ }
738+
730739func errAtLeastOneArgument (command string ) error {
731740 return fmt .Errorf ("%s requires at least one argument" , command )
732741}
@@ -738,3 +747,12 @@ func errExactlyOneArgument(command string) error {
738747func errTooManyArguments (command string ) error {
739748 return fmt .Errorf ("Bad input to %s, too many arguments" , command )
740749}
750+
751+ // getShell is a helper function which gets the right shell for prefixing the
752+ // shell-form of RUN, ENTRYPOINT and CMD instructions
753+ func getShell (c * container.Config ) []string {
754+ if 0 == len (c .Shell ) {
755+ return defaultShell [:]
756+ }
757+ return c .Shell [:]
758+ }
0 commit comments