时间可能不存在

没有追求的灵魂会很无趣

用户工具

站点工具


dockerfile

Dockerfile中CMD与ENTRYPOINT

  • ENTRYPOINT 是“命令”:它设置了容器启动时必须执行的主程序,这个设定很难被改变。
  • CMD 是“默认参数”:它为上面的“命令”提供默认的参数。如果用户在运行容器时提供了其他参数,CMD 提供的默认值就会被替换掉。

下面这个表格可以让你更直观地看到它们的不同:

特性 CMD ENTRYPOINT
:— :— :—
核心作用 提供默认的命令或参数,容易被覆盖 设定容器的主程序,确保其始终运行
参数覆盖 被 docker run 后面的全部参数覆盖 被 docker run 后面的参数追加到其命令末尾
覆盖方式 docker run <image> <new_command> 完全替换 CMD 除非使用 --entrypoint 标志,否则无法轻易覆盖

📌 用法对比与示例

光看理论还不够直观,我们来看看具体例子。

1. 只用 `CMD`:容易被“替换”的默认行为

假设 Dockerfile 里写着 CMD ["ls"]。 * 当你运行 docker run my-image 时,容器会执行 ls,列出目录内容。 * 如果你运行 docker run my-image -l,这时 docker run 后面的 -l 会覆盖掉 CMD 指定的 ls,导致容器尝试执行 -l 这个命令,从而报错。这是因为 ls 这个命令被完全替换掉了。

2. 只用 `ENTRYPOINT`:固定命令,参数可追加

假设 Dockerfile 里写着 ENTRYPOINT ["ls"]。 * 当你运行 docker run my-image 时,效果和上面一样,执行 ls。 * 当你运行 docker run my-image -l 时,-l 会被追加到 ENTRYPOINT 命令的后面,最终执行的命令是 ls -l。这能成功实现你想要的详细列表输出。

3. 强强联手:`ENTRYPOINT` + `CMD`(推荐做法)

这是一种很常用也推荐的做法,结合了二者的优点:用 ENTRYPOINT 固定主程序,用 CMD 提供灵活的默认参数。

snippet.dockerfile
ENTRYPOINT ["curl"]
CMD ["https://example.com"]

在这个例子里: * 运行 docker run my-image,实际执行 curl https://example.com。 * 运行 docker run my-image https://api.github.com,CMD 的默认 URL 被覆盖,实际执行 curl https://api.github.com。

🛠️ 如何强制覆盖 `ENTRYPOINT`?

虽然 ENTRYPOINT 被设计为不容易被覆盖,但确实有一个方法:在 docker run 时使用 --entrypoint 标志。

例如,无论 Dockerfile 里的 ENTRYPOINT 是什么,执行下面的命令都会让容器运行 sh 命令:

snippet.bash
docker run --entrypoint sh my-image

这通常用于调试或紧急情况下,临时进入容器内部。

⚠️ 两种格式的选择:Exec 格式 vs Shell 格式

使用 CMD 和 ENTRYPOINT 时,有两种写法,强烈建议优先使用 Exec 格式(即带中括号的写法)。

  • Exec 格式:CMD ["executable", "param1", "param2"] 或 ENTRYPOINT ["executable", "param1"]。这是推荐写法,它会直接执行程序,信号处理正常。
  • Shell 格式:CMD command param 或 ENTRYPOINT command param。这种写法会通过 /bin/sh -c 启动一个子进程来执行命令,可能导致容器无法正常收到退出信号,并且在 ENTRYPOINT 下,docker run 的追加参数可能失效。
dockerfile.txt · 最后更改: 由 chenyang