【问题标题】:Dockerfile unable to execute CMD command (docker for windows)Dockerfile 无法执行 CMD 命令(docker for windows)
【发布时间】:2019-03-14 08:11:10
【问题描述】:

在 dockerfile 中无法在 docker for windows 上执行 CMD 命令。

我想使用 CMD 运行几个命令,但是连一个命令都无法运行。

我已经尝试了以下方法,但没有任何效果......

1.

CMD "sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"

2.

RUN ["powershell", "-NoProfile", "-Command", "c:\db\db_scripts\script.ps1"]

3.

CMD ["cmd", "sqlcmd", "-S", "database", "-i", "C:\db\db_scripts\upgradescript.sql", "-U", "sa", "-P", "mypassword"]

4.

ARG arg1=database
ARG arg2=C:\db\db_scripts\upgradescript.sql
ARG arg3=sa
ARG arg4=mypassword!

RUN ["cmd", "-NoProfile", "-Command", "sqlcmd -S $env:arg1 -i $env:arg2 -U $env:arg3 -P $env:arg4"]

5.

RUN powershell.exe  c:\db\db_scripts\script.ps1

6。

ENTRYPOINT ["powershell", "-NoProfile", "-Command", "sqlcmd"]
CMD ["-S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"]

支持文件:

A. Script.ps1(2、5使用)

cmd /c "sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"

B. Dockerfile

# escape=`

FROM microsoft/mssql-server-windows-developer
COPY db\* c:\db\
COPY db_scripts\* c:\db\db_scripts\
ENV attach_dbs="[{'dbName':'ABC','dbFiles':['C:\db\ABC.mdf','C:\db\ABC_Log.ldf']},{'dbName':'XYZ','dbFiles':['C:\db\XYZ.mdf','C:\db\XYZ_Log.ldf']}]"
CMD "sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"

请注意,由于转义字符,我不需要使用“\\”。

观察

容器启动并在几秒钟后消失。

如果我删除 CMD 部分,容器就可以正常工作。我可以进入容器并可以在cmd shell 中运行上述sqlcmd 命令。

我做错了什么,缺少什么,任何更好的方法等。有人可以提供一些指导吗?谢谢!

编辑:

根据 Josh 的回答,这个 ENTRYPOINT 命令对我有用的唯一方法是(分享以便其他人可以受益,甚至发布更好的方法)...

ENV arg1 database
ENV arg2 C:\db\db_scripts\upgradescript.sql
ENV arg3 sa
ENV arg4 mypassword
ENTRYPOINT ["powershell sleep(60); sqlcmd"]
CMD ["-S $env:arg1 -i $env:arg2 -U $env:arg3 -P $env:arg4"]

【问题讨论】:

    标签: docker containers dockerfile docker-container docker-for-windows


    【解决方案1】:

    我认为您可能误解了 CMD 与 ENTRYPOINT 与 RUN 指令的性质。 CMD 和 ENTRYPOINT 都在容器启动/运行时生效,而 RUN 是构建时命令。有点令人困惑的是,您在 docker 构建过程中使用 RUN 来准备容器映像,而 CMD 是在容器中运行的。

    通过documentation

    CMD 的主要目的是为正在执行的容器提供默认值...

    任何给定的容器映像都只会有一个 CMD 指令。

    一个 Dockerfile 中只能有一个 CMD 指令。如果你列出了多个 CMD,那么只有最后一个 CMD 会生效。

    如果你想确保一个可执行文件在容器启动时运行,那么你可以考虑使用 ENTRYPOINT 指令;将 ENTRYPOINT 视为为 CMD 指令提供默认值的命令。来自文档:

    Dockerfile 应至少指定 CMD 或 ENTRYPOINT 命令之一。 将容器用作可执行文件时应定义 ENTRYPOINT。 CMD 应该用作为 ENTRYPOINT 命令或在容器中执行临时命令定义默认参数的一种方式。 使用替代参数运行容器时,CMD 将被覆盖。

    RUN 命令是一个构建时指令,用于准备包含必要文件、配置等的容器映像。

    有关 ENTRYPOINT 与 CMD 的更多信息,请参阅 this SO question

    ED:您正在查看的情况是,在容器中运行 SQL 脚本是一个棘手的问题,因为在数据库引擎准备好接受命令之前,该脚本不得运行。作为第一步,您可以在 ENTRYPOINT 指令中运行升级脚本。您还可以考虑通过docker exec 命令在容器配置后运行 SQL 升级脚本。

    ED2:提供的示例:

    ENTRYPOINT ["powershell", "-NoProfile", "-Command", "sqlcmd"] CMD ["sqlcmd -S database -i C:\db\db_scripts\upgradescript.sql -U sa -P mypassword"]

    不起作用,因为它会导致可能是无意义的命令行指令。请记住,CMD 为 ENTRYPOINT 指令提供参数,因此您只需在 ENTRYPOINT 中指定 powershell sqlcmd,让 CMD 提供参数(这是未经测试的,OTOMH):

    ENTRYPOINT powershell sqlcmd -S database -U sa -P mypassword -i

    CMD C:\db\db_scripts\upgradescript.sql

    ED 3: 通过组合这两个语句并将语句终止符 (;) 添加到 ENTRYPOINT,您可以允许标准 SQL 容器 .\Start.ps1 脚本运行,该脚本进入一个无限循环,阻止容器立即停止(容器仅在其中执行的进程正在运行时运行)。这保证了您的启动脚本被执行,即使用户在运行时覆盖了 CMD 指令:

    ENTRYPOINT powershell "sqlcmd -S database -U sa -P mypassword -i 'C:\db\db_scripts\upgradescript.sql';"

    CMD .\Start.ps1

    【讨论】:

    • 很好的描述!我确实尝试过使用我忘记提及的入口点,并添加为第 6 个项目符号。它也没有工作。将对其进行更多研究。如果您认为我的语法或方法不正确,请指导。谢谢!
    • 我添加了一个潜在的尝试方法
    • 如果我的答案有理由被否决,这将有助于我了解我的错误之处,以便我可以学习和改进以备将来使用。谢谢
    • 你的回答很棒
    • 正如我所说,这是一个很好的答案,我只是在测试不同的入口点组合,一旦它工作,将更新 ED2 或添加 ED3 作为直接答案。再次感谢乔希!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-12
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多