【问题标题】:CMD and ENTRYPOINT with script, same Dockerfile带有脚本的 CMD 和 ENTRYPOINT,相同的 Dockerfile
【发布时间】:2021-11-30 09:57:10
【问题描述】:

尝试使用此Dockerfile 运行基于图像的 pod:

...

ENTRYPOINT [ "./mybashscript", ";", "flask" ]
CMD [ "run" ]

我希望完整的命令是./mybashscript; flask run。 但是,在本例中,pod / container 执行 ./mybashscript 而不是 flask

我还尝试了几种变体,例如:

...

ENTRYPOINT [ "/bin/bash", "-c", "./mybashscript && flask" ]
CMD [ "run" ]

现在,flask 被执行,但 run 被忽略。

PS:我试图理解为什么这不起作用,并且我知道我可以将所有内容放入 entrypoint 或将所有内容放入 bash 脚本中,但这不是重点。

【问题讨论】:

    标签: docker kubernetes dockerfile containers kubernetes-pod


    【解决方案1】:

    在此处显示的两种情况下,您都使用 JSON 数组 exec form 来表示 ENTRYPOINTCMD。这意味着不运行任何 shell,除非在第二种情况下显式运行它。这两部分只是combined together into a single command

    第一个构造运行脚本./mybashscript,它必须是可执行的并且有一个有效的“shebang”行(可能是#!/bin/bash)。该脚本传递了三个参数,您可以在 shell 变量 $1$2$3 中看到它们:分号 ;flaskrun

    第二个构造运行/bin/sh -c './mybashscript && flask' runsh -c 接受一个参数,即mybashscript && flask;剩余的参数run 被解释为位置参数,sh -c 命令会将其视为$0


    您显示的ENTRYPOINTCMD 的任意拆分实际上没有任何意义。两者之间唯一真正重要的区别是,在运行容器时更容易更改CMD,例如将其放在docker run 命令中的图像名称之后。将所有命令放在命令部分或不放在命令部分是有意义的,但实际上将一半命令放在一个部分,一半放在另一个部分。

    我在这里的第一关是写:

    # no ENTRYPOINT
    CMD ./mybashscript && flask run
    

    Docker 将在裸字符串shell form 中为您插入一个sh -c 包装器,因此&& 具有其通常的Bourne-shell 含义。


    此设置看起来您正在尝试在主容器命令之前运行初始化脚本。有一个合理的标准模式是为此使用ENTRYPOINT。由于它通过CMD 作为参数传递,脚本可以以exec "$@" 结尾来运行CMD(可能在docker run 命令中被覆盖)。入口点脚本可能看起来像

    #!/bin/sh
    # entrypoint.sh
    ./mybashscript
    exec "$@"
    

    (如果你写了mybashscript,你也可以用exec "$@" 行结束它,并使用该脚本作为入口点。)

    在 Dockerfile 中,将此包装脚本设置为ENTRYPOINT,然后将主命令设置为CMD

    ENTRYPOINT ["./entrypoint.sh"] # must be a JSON array
    CMD ["flask", "run"]           # can be either form
    

    如果您提供备用命令,它将替换 CMD,因此 exec "$@" 行将运行该命令而不是 Dockerfile 中的命令,但 ENTRYPOINT 包装器仍会运行。

    # See the environment the wrapper sets up
    docker run --rm your-image env
    # Double-check the data directory setup
    docker run --rm -v $PWD/data:/data your-image ls -l /data
    

    如果您真的想要使用sh -c 形式和拆分ENTRYPOINT,那么sh -c 中的命令必须读取$@ 才能找到它的位置参数(@987654367 @),另外你需要知道第一个参数是$0 而不是$1。如果您编写,您显示的表单将是有效的

    # not really recommended but it would work
    ENTRYPOINT ["/bin/sh", "-c", "./mybashscript && flask \"$@\"", "flask"]
    CMD ["run"]
    

    【讨论】:

    • 老兄非常感谢清晰详细的回答!我涵盖了所有这些可能性,除了最后一个。脚本mybashscript 实际上称为boostrap,正如您正确假设的那样,它包含初始化指令。所以基本上我想运行那个脚本,我希望run 成为flask 的默认参数,就像你在上一个例子中建议的那样。我倾向于参考您的第二个建议,我将其重命名为 bootstrapentrypoint 并将 CMD 作为脚本的默认参数。你有什么建议?
    • 顺便说一句,在最后一个示例中的entrypoint 中,不应该是ENTRYPOINT ["/bin/sh", "-c", "./mybashscript && \"$@\"", "flask"] 吗?由于 $@$0 开头,所以您最终会得到 ... && flask flask run ... ,对吧?
    • 我的建议是使用入口点包装脚本进行设置,然后使用CMD flask run 使其成为一个完整的格式良好的 shell 命令。
    • $@ 扩展 starts from parameter one 因此,在显式 sh -c 形式中,您需要在 -c 命令之后添加一个单词以成为 $0,但它被忽略了。
    猜你喜欢
    • 2014-02-28
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    相关资源
    最近更新 更多