在 CMD 之前执行一个脚本 [英] Execute a script before CMD

查看:26
本文介绍了在 CMD 之前执行一个脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 Docker 文档:一个 Dockerfile 中只能有一个 CMD 指令.如果你列出了多个 CMD,那么只有最后一个 CMD 会生效.

As per Docker documentation: There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.

我希望在 CMD 命令(在我的例子中是 init)之前执行一个简单的 bash 脚本(它处理 docker 环境变量).

I wish to execute a simple bash script(which processes docker environment variable) before the CMD command(which is init in my case).

有什么办法吗?

推荐答案

使用自定义入口点

创建一个自定义入口点来执行您想要的操作,然后在最后执行您的 CMD.

Use a custom entrypoint

Make a custom entrypoint which does what you want, and then exec's your CMD at the end.

注意:如果您的图像已经定义了一个自定义入口点,您可能需要扩展它而不是替换它,或者您可能会更改您需要的行为.

NOTE: if your image already defines a custom entrypoint, you may need to extend it rather than replace it, or you may change behavior you need.

entrypoint.sh:

#!/bin/sh

## Do whatever you need with env vars here ...

# Hand off to the CMD
exec "$@"

Dockerfile:

COPY entrypoint.sh /entrypoint.sh
RUN chmod 755 /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

Docker 将使用 CMD 作为参数运行您的入口点.如果你的 CMD 是 init,那么:

Docker will run your entrypoint, using CMD as arguments. If your CMD is init, then:

/entrypoint.sh init

入口点脚本末尾的 exec 负责在入口点完成所需执行的操作后移交给 CMD.

The exec at the end of the entrypoint script takes care of handing off to CMD when the entrypoint is done with what it needed to do.

ENTRYPOINT 和 CMD 的使用经常让 Docker 新手感到困惑.在评论中,您对此表示困惑.以下是它的工作原理和原因.

The use of ENTRYPOINT and CMD frequently confuses people new to Docker. In comments, you expressed confusion about it. Here is how it works and why.

ENTRYPOINT 是在容器内运行的初始内容.它将 CMD 作为参数列表.因此,在这个例子中,容器中运行的是这个参数列表:

The ENTRYPOINT is the initial thing run inside the container. It takes the CMD as an argument list. Therefore, in this example, what is run in the container is this argument list:

# ENTRYPOINT = /entrypoint.sh
# CMD        = init
["/entrypoint.sh", "init"]

# or shown in a simpler form:
/entrypoint.sh init

图像不需要有入口点.如果没有定义,Docker 有一个默认值:/bin/sh -c.

It is not required that an image have an ENTRYPOINT. If you don't define one, Docker has a default: /bin/sh -c.

所以在你原来的情况下,没有 ENTRYPOINT,并且使用 init 的 CMD,Docker 会运行这个:

So with your original situation, no ENTRYPOINT, and using a CMD of init, Docker would have run this:

/bin/sh -c 'init'
^--------^  ^--^
    |         ------- CMD
    --------------- ENTRYPOINT

一开始,Docker 只提供 CMD,而 /bin/sh -c 被硬编码为 ENTRYPOINT(您无法更改它).在此过程中的某个时刻,人们遇到了他们必须做更多自定义事情的用例,而 Docker 公开了 ENTRYPOINT,因此您可以将其更改为您想要的任何内容.

In the beginning, Docker offered only CMD, and /bin/sh -c was hard-coded as the ENTRYPOINT (you could not change it). At some point along the way, people had use cases where they had to do more custom things, and Docker exposed ENTRYPOINT so you could change it to anything you want.

在我上面展示的示例中,ENTRYPOINT 被替换为自定义脚本.(虽然它最终仍然由 sh 运行,因为它以 #!/bin/sh 开头.)

In the example I show above, the ENTRYPOINT is replaced with a custom script. (Though it is still ultimately being run by sh, because it starts with #!/bin/sh.)

ENTRYPOINT 将 CMD 作为参数.entrypoint.sh 脚本的末尾是 exec "$@".由于 $@ 扩展为提供给脚本的参数列表,因此变成了

That ENTRYPOINT takes the CMD as is argument. At the end of the entrypoint.sh script is exec "$@". Since $@ expands to the list of arguments given to the script, this is turned into

exec "init"

因此,当脚本完成时,它会消失并被 init 替换为 PID 1.(这就是 exec 所做的 - 它替换 使用不同命令的当前进程.)

And therefore, when the script is finished, it goes away and is replaced by init as PID 1. (That's what exec does - it replaces the current process with a different command.)

在评论中,您询问了在 Dockerfile 中添加 CMD 的问题.是的,你可以这样做.

In the comments, you asked about adding CMD in the Dockerfile. Yes, you can do that.

Dockerfile:

CMD ["init"]

或者,如果您的命令还有更多内容,例如init -a -b 之类的参数看起来像这样:

Or if there is more to your command, e.g. arguments like init -a -b, would look like this:

CMD ["init", "-a", "-b"]

这篇关于在 CMD 之前执行一个脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆