New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CMD works incorrectly on Windows when ENTRYPOINT is specified #33373
Comments
Looks to be specific to Windows; I tried this on a Linux version of docker-ce 17.05, and got this; $ docker build -t foo -<<EOF
FROM busybox
ENTRYPOINT echo START
CMD ["echo", "hi"]
EOF
$ docker run --rm foo
START I tried on older versions (docker 1.10 and up), which showed the same behaviour as above. Personally, I wouldn't have been against allowing mixed notation, and just accept JSON arguments as arguments to the Adding a warning sounds good to me though, so that the user is aware of the |
I've noticed this before and I suspect we didn't do the normal "CMD overrides the args of ENTRYPOINT" because it would have involved parsing the ENTRYPOINT string and understanding things like quotes, etc. While today we have parsers for that, originally we didn't, so we were stuck with this odd behavior. Changing it would be a breaking change, but you have to wonder who we would break since CMD is ignored today, which means people probably aren't mixing like this. We could try to parse ENTRYPOINT (when its a string) and ignore its args IFF CMD is present, and see how that works/feels. A warning wouldn't be bad I guess, but I'd worry people will miss it in the flood of output. I'd almost prefer to make it an error so people are forced to 'fix' their Dockerfile - since ignoring user's inputs is probably a bad thing to do in general. |
@duglin the issue here is that the behaviour on Windows looks to be different than the behaviour on Linux; Windows:
vs Linux:
That's something that needs to be addressed at least; the warning is more a "nice to have", but separate from this issue 👍 |
True - I assumed Windows would be fixed to give the same "odd" behavior as linux :-) so I focused on the more interesting aspect of it. |
Ah, yes, it should probably get the same "odd" behavior |
https://docs.docker.com/engine/reference/builder/#entrypoint
https://docs.docker.com/engine/reference/builder/#shell-form-entrypoint-example
I think if ENTRYPOINT is in shell form, container build process should fail if CMD statement presents. Also docker run should display warning if ENTRYPOINT is in shell form, but arguments were provided. |
https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
|
I'm trying to use the exec form of both instructions with a powershell script, and I'm finding that the exec form for ENTRYPOINT simply doesn't parse correctly at all - here's a simple DOCKERFILE to demo:
where
This SO Q&A seems to suggest that "shell" form does behave as expected - something that I've been able to verify in my own testing. |
You're missing escaping of the backslash in ENTRYPOINT. Otherwise it's not valid JSON. So it's trying to treat it as a direct command (non-JSON) which is why the open square brace is erroring. Also you shouldn't need to escape in the COPY |
Hmm. I think I'm missing part of how the commands are parsed and passed to the shell. Why does the backslash need to be escaped for my example, but in the Doc man it has this example with unescaped backslashes? Is it because I'm using
docker docs sample:
EDIT:
It will parse correctly as the powershell command |
No. Double backslash. This is straight JSON |
Thanks for being patient with me and repeating yourself until I finally understood the JSON escaping, @jhowardmsft! You're right as well about there not being a need to escape the COPY command - I had kept it in from an older DOCKERFILE I had Having corrected that problem, I now have another question. If I've specified I'm seeing this (abridged for brevity), which I speculate could mean that the command
ed: change container name to avoid confusion |
No I don't believe so and the error confirms that. No shell was used at all, and a .ps1 file isn't an executable without PS. I need to look at code though and am OOF ATM to absolutely confirm. A JSON entrypoint will ignore the shell regardless. If you exec form the entrypoint you should get the desired behaviour you want, and the shell will be used. |
Hmmm, thanks for confirming that. I wanted the behavior of an executable, with arguments to I originally came down this path because I was having problems importing/invoking a custom powershell module prior to specifying ENTRYPOINT. I think that I'll try to tackle this again with my new-found knowledge and see if I can figure out where I malfed up - thanks again! |
Why not just add "powershell", "-command" to the entrypoint? |
good question and something I tried; the run-time parameter that users would pass is a string looking something like In the scenario I've been working with, I've found that unless I wrap the argument in both a Here's a version of the CLI command that fails to preserve the argument:
Wrapping the string with an addition set of here's DOCKERFILE snippet (note that the default CMD is correctly used when nothing is provided to
Could this have less to do with ENTRYPOINT and more to do with how I'm gonna need to go back and re-test my approach that used |
Wanted to leave an update with some explorations I've made in this area. I wasn't able to isolate any specific issues with ENTRYPOINT but I have gained some insights that I thought could be useful to other people looking to add to their understanding. I'm really happy with the pattern I've settled upon which uses the shell form of both ENTRYPOINT and CMD: The service I'm hosting in the container requires some runtime configuration, which is achieved with a powershell script that is set as the ENTRYPOINT instruction. Thanks again @jhowardmsft for the guidance! Once the configuration parameters have been modified, a separate Start script is invoked (by the CMD instruction) which enters an infinite loop that returns event log entries. The key is to ensure that a trailing In other words, the pattern looks like this (note the trailing Configure
Run
No matter how I start my container, I can be confident that the necessary setup tasks have been ran. If I want to debug or perform other operations, I simply pass a command to docker run, overriding the |
I'll take this. Needed as part of the containerd runtime changes. |
Aha, the answer to this is hilarious. After scanning the moby codebase, along with containerd and runc, there's nothing explicit in any of that code to strip the "CMD" part. It's actually shell behaviour. So
will generate a container config similar to below with both Cmd and Entrypoint populated: When a container is run from that image, the OCI spec is process bit is populated as follows: Note both the entrypoint and the cmd are both in there. However, if you look at ps, you'll notice "world" isn't present. It turns out, this is entirely shell behaviour on Linux (that the "CMD" part is dropped if the ENTRYPOINT is in shell form). Which is completely different to how command line parsing works on Windows: So to fix this, I may be able to do a Windows-targeted fix in moby and drop the CMD part from OCI if the entrypoint is shell form. I'm already heavily all-over that code for containerd integration on Windows, but might give it a go to fix building on what I already have. However, it might be a bit contentious as I will need to store the fact that ENTRYPOINT is shell form in the config so as to know to drop the CMD part when building the OCI spec prior to passing it to the runtime. IOW, make the OCI spec so that it doesn't have the "world" part in it. However, kind of low priority to do right now. |
It seems that if you use an entrypoint/cmd with incorrect escape sequences the Dockerfile parser will add the shell to the entrypoint entry. And the escape directive ( So this is broken: FROM mcr.microsoft.com/dotnet/framework/sdk:4.8
ENTRYPOINT ["dotnet", "s\w.dll" ] It will produce this entrypoint (check with "Entrypoint": [
"powershell -Command $ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; [\"dotnet\", \"s\\w.dll\"]"
], While this works: FROM mcr.microsoft.com/dotnet/framework/sdk:4.8
ENTRYPOINT ["dotnet", "s\\w.dll" ] And will produce this entrypoint: "Entrypoint": [
"dotnet",
"s\\w.dll"
], |
@giggio could you open a separate ticket for that? |
Ok, done: #39779 |
Description
If ENTRYPOINT is in shell format and CMD is in JSON format, ENTRYPOINT should be ignored.
Steps to reproduce the issue:
Describe the results you received:
Describe the results you expected:
#1 returns error. It's correct.
#2 prints message. It's wrong. It should return error, because CMD is in JSON format.
Additional information you deem important (e.g. issue happens only occasionally):
https://docs.docker.com/engine/reference/builder/#cmd
Output of
docker version
:Output of
docker info
:The text was updated successfully, but these errors were encountered: