2

I'm building a Windows based docker image:

FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019

# omitted for brevity

ENTRYPOINT ["c:\spinner.exe", "service", "w3svc", "-t", "c:\iislog\W3SVC\u_extend1.log"]

The base image sets the shell to Powershell:

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

My understanding was that when the exec form of the ENTRYPOINT instruction is used, the command will be executed without a shell. However, when I create the container, it fails with this error:

$ docker run -d -p 80:80 --isolation process --name pht site:local


$ docker logs pht

At line:1 char:77
+ ... ference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; [C:\\spin ...
+                                                                  ~
Missing ] at end of attribute or type literal.
At line:1 char:78
+ ... '; $ProgressPreference = 'SilentlyContinue'; [C:\\spinner.exe, servic ...
+                                                    ~~~~~~~~~~~~~~
Unexpected token ':\\spinner.exe' in expression or statement.
At line:1 char:92
+ ... ; $ProgressPreference = 'SilentlyContinue'; [C:\\spinner.exe, service ...
+                                                                 ~
Missing argument in parameter list.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordEx
   ception
    + FullyQualifiedErrorId : EndSquareBracketExpectedAtEndOfAttribute

And when I inspect the stopped container, I see the executed command was through shell:

 "Entrypoint": [
                "powershell -Command $ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; [\"c:\\spinner.exe\", \"service\", \"w3svc\", \"-t\", \"c:\\iislog\\W3SVC\\u_extend1.log\"]"
            ],

Am I misunderstanding something here?

Amir Keibi
  • 1,991
  • 28
  • 45

1 Answers1

3

The exec syntax requires JSON format, which means that \ instances in the array elements must be escaped as \\.

Since your ENTRYPOINT instruction therefore does not contain a valid JSON array, it looks like Docker is falling back to shell syntax and therefore passes your ENTRYPOINT argument to the shell, which in your case is PowerShell, as defined in your SHELL instruction - and that results in a broken shell command.[1]

A syntactically correct ENTRYPOINT in exec format - i.e., valid JSON - prevents involvement of a shell, which is the correct approach in this case, given that your command contains literal elements only.

Therefore, try the following (\ instances escaped as \\):

ENTRYPOINT ["c:\\spinner.exe", "service", "w3svc", "-t", "c:\\iislog\\W3SVC\\u_extend1.log"]

That way, Docker should end up executing the following command line in the container:

c:\spinner.exe service w3svc -t c:\iislog\W3SVC\u_extend1.log

[1] What happens is that the malformed ENTRYPOINT argument, ["c:\spinner.exe", "service", "w3svc", "-t", "c:\iislog\W3SVC\u_extend1.log"], is taken to be a single argument - a verbatim string to be escaped based on JSON rules (doubling of \ chars.) - to be passed to the shell, as defined by your SHELL instruction. This means appending that argument to the last argument of your SHELL array, preceded by a space character. What you saw in the logs is evidence of that.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    You're right! It didn't occur to me that backslashes in Json were the problem. I even changed the escape character for the Dockerfile to backtick thinking that'll propagate to the command, but it doesn't. – Amir Keibi Oct 04 '19 at 18:39
  • 1
    Glad to hear it worked, @AmirKeibi. My _guess_ is that the configurable escape character only applies to _unquoted_ arguments and line-continuation. – mklement0 Oct 04 '19 at 19:16