Skip to content

Builder shell configuration#22489

Merged
vdemeester merged 1 commit intomoby:masterfrom
microsoft:jjh/shell
Jun 5, 2016
Merged

Builder shell configuration#22489
vdemeester merged 1 commit intomoby:masterfrom
microsoft:jjh/shell

Conversation

@lowenna
Copy link
Member

@lowenna lowenna commented May 4, 2016

Signed-off-by: John Howard [email protected]

This PR simplifies, particularly for Windows users, although this is not limited to Windows only, the ability to change the default shell when using the shell form for commands in a dockerfile. This alleviates (as put in the documentation update) the two inefficiencies being a) an extra command process (cmd) has been started on Windows and b) the frequent occurrence of RUN powershell -command foo bar in Dockerfiles.

Example (also in doc update) below:

PS E:\docker\build\shell> docker build -t shell  --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM windowsservercore
 ---> dbfee88ee9fd
Step 2 : SHELL powershell -command
 ---> Running in 47e4e97b03b5
 ---> c7bd22f61e65
Removing intermediate container 47e4e97b03b5
Step 3 : RUN New-Item -ItemType Directory C:\\Example
 ---> Running in 1cd80dd20c31


    Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         5/3/2016   5:01 PM                Example


 ---> 5bf91df219c6
Removing intermediate container 1cd80dd20c31
Step 4 : WORKDIR C:\\Example
 ---> Running in 7c45f946effc
 ---> 98a52497e225
Removing intermediate container 7c45f946effc
Step 5 : ADD Execute-MyCmdlet.ps1 .
 ---> 5363cf797edb
Removing intermediate container d8d0ecc4f532
Step 6 : RUN .\Execute-MyCmdlet -sample 'hello world'
 ---> Running in 00019129cfc3
Hello from Execute-MyCmdlet.ps1 - passed hello world
 ---> c7d63c58e196
Removing intermediate container 00019129cfc3
Successfully built c7d63c58e196
PS E:\docker\build\shell>

@taylorb-microsoft

@lowenna
Copy link
Member Author

lowenna commented May 4, 2016

Perhaps a good example of craziness can be found in the busybox dockerfile that's used on windowsTP5 CI. https://github.com/jhowardmsft/busybox/blob/master/Dockerfile In the RUN, extra escaping is needed for cmd, conveniently the carat, making the actual command that's needed even more obfuscated. This PR would allow that dockerfile to be simplified, and far more readable to someone maintaining it. I'm sure there are countless other examples out there.

@justincormack
Copy link
Contributor

Isn't it just easier to use the json form? I know it is a bit more verbose to write, but it already achieves what you want, not running an extra shell and not requiring escaping (other than double quotes)?

@lowenna
Copy link
Member Author

lowenna commented May 4, 2016

Not in my experience. Ease of use trumps verbosity and readability IMO

@cpuguy83
Copy link
Member

cpuguy83 commented May 5, 2016

This is not the first time there's been a similar discussion.... unfortunately buried in GitHub issues.

@lowenna
Copy link
Member Author

lowenna commented May 5, 2016

I'm sure there have, but I'm not aware of any which involve the Windows angle where it's a far more acute issue.

@thaJeztah
Copy link
Member

ping @docker/core-engine-api-maintainers we want to have a broader opinion on this one, so please give your +1 or -1. We'll revisit in a week or so to see if we move forward

@tianon
Copy link
Member

tianon commented May 12, 2016

+1, and agree with @justincormack that the JSON syntax is probably more consistent

@jessfraz
Copy link
Contributor

+1! (maybe counts as 1/2 a vote)

@thaJeztah
Copy link
Member

@jfrazelle haha, should've sneaked into the hangout :)

We discussed this (again), and there were no objections from the people present in the maintainers meeting (hangout), so moved this to code review

@lowenna
Copy link
Member Author

lowenna commented May 26, 2016

Nah, I think that counts as at least 2 votes 😸

@tarunlalwani
Copy link

@thaJeztah, which release can get this change? 1.11.2?

@thaJeztah
Copy link
Member

@tarunlalwani no this is an API change, so it doesn't go into a patch release, so will go into 1.12.0

@thaJeztah thaJeztah added this to the 1.12.0 milestone May 30, 2016
@thaJeztah
Copy link
Member

Erm, meant change in the Dockerfile, not API

@thaJeztah
Copy link
Member

@jhowardmsft @tianon @jfrazelle thinking about this feature some more; some questions;

  • do we want only a single SHELL to be allowed in a Dockerfile? (at least, to start with)
  • should SHELL be inherited from the FROM image? Having it inherit could be very confusing for users, because they don't know what shell is set in the base image.
  • Could this feature be abused to run arbitrary code on each RUN? Is this a concern? Should we limit accepted values for SHELL for that reason?
  • Which instructions are affected by SHELL? We need to be explicit about this; do ENTRYPOINT and CMD also use this? Do we want them to?

@tarunlalwani
Copy link

tarunlalwani commented May 30, 2016

@thaJeztah, I have not been asked still would like to add my opinions :)

  • do we want only a single SHELL to be allowed in a Dockerfile? (at least, to start with)

Multiple should be allowed and just overwrites the previous SHELL entry

  • should SHELL be inherited from the FROM image? Having it inherit could be very confusing for users, because they don't know what shell is set in the base image.

    Inheritance should be allowed, that is the main reason for asking such a feature. But docker can print a warning "Using non-default shell /bin/bash -lc"

  • Could this feature be abused to run arbitrary code on each RUN? Is this a concern? Should we limit accepted values for SHELL for that reason?

    Not sure on this, probably I would let others comment

  • Which instructions are affected by SHELL? We need to be explicit about this; do ENTRYPOINT and CMD also use this? Do we want them to?

    SHELL should only impact the RUN command, which is a BUILD command and not touch ENTRYPOINT and CMD

@vdemeester
Copy link
Member

  • do we want only a single SHELL to be allowed in a Dockerfile? (at least, to start with)

Multiple SHELL, working like WORKDIR 😝. This way you could setup some magic shell while building the image and reset it to a sane default before the end of the build…

  • should SHELL be inherited from the FROM image? Having it inherit could be very confusing for users, because they don't know what shell is set in the base image.

I would say yes too but I see the confusion coming too 😓. And combined with the next one (running arbitrary code) it might be safer for this to not inherit.

  • Could this feature be abused to run arbitrary code on each RUN? Is this a concern? Should we limit accepted values for SHELL for that reason?

It definitely could but limiting accepted values is not gonna be good either. I'm definitely worried about that one though (and is almost a stopper for me 😓). With inherinting, to be safe, you would have to setup the shell to your sane default for each image you wanna build (which parent is not maintained by you) — it's gonna add noise and more not useful layers.

  • Which instructions are affected by SHELL? We need to be explicit about this; do ENTRYPOINT and CMD also use this? Do we want them to?

Definitely only RUN.

Although I really like the idea and the hacking (in the good sence of it) it brings, I'm still a little bit meh / worried about having this in the Dockerfile(s).

@duglin
Copy link
Contributor

duglin commented May 31, 2016

I'm not so sure that SHELL shouldn't apply to ENTRYPOINT and CMD too since those wrapper cmds with "sh -c" too. Clearly on Windows "sh -c" isn't going to work for ENTRYPOINT/CMD so why wouldn't it apply there too?

And yes, I think it should be inherited and therefore should be kept in the image metadata.

@thaJeztah
Copy link
Member

thaJeztah commented May 31, 2016

Clearly on Windows "sh -c" isn't going to work for ENTRYPOINT/CMD so why wouldn't it apply there too?

On windows, it would default to CMD.exe

And yes, I think it should be inherited and therefore should be kept in the image metadata.

I'm really not sure about that; same as with the escape, we don't inherit that, because users wouldn't know what the escape character is. Similarly, they wouldn't know what the shell is in the commands they run.

Perhaps it's not a direct responsibility for Docker, but I'm kinda worried about inheriting this, not only because it could be exploited in nasty ways (setting the shell to a script that uploads env?), but also because of the confusion mentioned above

Signed-off-by: John Howard <[email protected]>
@tianon
Copy link
Member

tianon commented Jun 3, 2016

LGTM

@lowenna lowenna removed the status/failing-ci Indicates that the PR in its current state fails the test suite label Jun 3, 2016
Healthcheck = "healthcheck"
User = "user"
Volume = "volume"
Workdir = "workdir"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't help myself. Needed putting in order :)

@duglin
Copy link
Contributor

duglin commented Jun 3, 2016

LGTM once janky is happy

@tarunlalwani
Copy link

tarunlalwani commented Jun 4, 2016

Quick question

There is a command like sh -c "command" and sh -l -c "command". In first case if I define SHELL as sh -c then how would the run command look like? In second case if I use SHELL as sh -l, how would the RUN command be written?

@lowenna
Copy link
Member Author

lowenna commented Jun 4, 2016

First one is same as default on Linux. RUN command. Second one would be RUN -c command

@tarunlalwani
Copy link

tarunlalwani commented Jun 4, 2016

@jhowardmsft, How does one differentiate between sh -l -c "param" and sh -l "-c param" where SHELL is defined as sh -l?

@lowenna
Copy link
Member Author

lowenna commented Jun 4, 2016

This PR does not change that. You can use escaping in the JSON form to distinguish between those.

@tarunlalwani
Copy link

@jhowardmsft , Got it!

@lowenna
Copy link
Member Author

lowenna commented Jun 5, 2016

@thaJeztah Docs review time? 😄

@thaJeztah
Copy link
Member

Oh, we have two! Yes, moving, I'll give it a look later

RUN Write-Host hello

# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit; one quote too many here (two quotes after /S)

@thaJeztah
Copy link
Member

LGTM, I wanted to do some other updates to this document, so I can address that quote while doing so

@thaJeztah
Copy link
Member

ping @vdemeester for review/merge

@vdemeester
Copy link
Member

LGTM 🐠

@vdemeester vdemeester merged commit df1dd13 into moby:master Jun 5, 2016
@thaJeztah
Copy link
Member

🎉 thanks @jhowardmsft!

@lowenna
Copy link
Member Author

lowenna commented Jun 5, 2016

Woohoo! Thanks!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants