powershell - Entrypoint的exec形式通过shell执行

标签 powershell docker dockerfile docker-entrypoint

我正在构建一个基于 Windows 的 docker 镜像:

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"]

基础镜像将 shell 设置为 Powershell:

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

我的理解是,当使用ENTRYPOINT指令的exec形式时,该命令将在没有shell的情况下执行。但是,当我创建容器时,它失败并出现以下错误:

$ 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

当我检查停止的容器时,我看到执行的命令是通过 shell 执行的:

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

我是不是误解了什么?

最佳答案

exec 语法需要 JSON 格式,这意味着数组元素中的 \ 实例必须转义为 \\

由于您的 ENTRYPOINT 指令不包含有效的 JSON 数组,看起来 Docker 正在回退到 shell 语法,因此会通过shell 的 ENTRYPOINT 参数(在您的例子中是 PowerShell,如您的 SHELL 指令中所定义),并且会导致 shell 命令损坏/em>.[1]

语法正确的ENTRYPOINT,采用exec格式 - 即有效的JSON - 防止 shell的参与,这是正确的在这种情况下的方法,假设您的命令仅包含文字元素。

因此,请尝试以下操作(\ 实例转义为 \\):

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

这样,Docker 最终应该在容器中执行以下命令行:

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

[1] 发生的情况是格式错误的 ENTRYPOINT 参数 ["c:\spinner.exe", "service", "w3svc", "-t", "c:\iislog\W3SVC\u_extend1.log"],被视为单个参数 - 基于 JSON 进行转义的逐字字符串规则(\ 字符加倍。) - 传递到 shell,如 SHELL 指令所定义。这意味着将该参数附加到 SHELL 数组的最后一个参数,前面有一个空格字符。您在日志中看到的就是证据。

关于powershell - Entrypoint的exec形式通过shell执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58210417/

相关文章:

ruby-on-rails - 在 Rails 项目上使用 capybara 和 selenium-webdriver 运行系统测试失败 : due to ArgumentError in bridge. rb:44:in `handshake

python - Micromamba 和 Dockerfile 错误 :/bin/bash: activate: No such file or directory

java - 如何运行 Docker 容器但不复制密码文件来组装镜像,还有其他选项吗?

docker - 入口点 : "entrypoint.sh" - docker compose

powershell - 使用PoSH取值,奇怪的结果

iis - 用于在 IIS 中查找当前绑定(bind)的过期证书的 Powershell 脚本

node.js - 跨容器传递容器IP以获取配置文件

docker - Docker多节点与集群中的一个节点

powershell - Powershell:使用foreach和listbox时输出奇数

powershell - 使用备用凭证复制项目