在编写 Dockerfile 时,CMD 与 ENTRYPOINT 两种指令在功能与用法上有何不同?请说明它们的交互方式及适用场景。
考察说明
考查对 Dockerfile 中 CMD 与 ENTRYPOINT 指令作用、区别及组合使用方式的理解。
回答思路
- 【回答框架 1】CMD 指令用于提供容器启动时的默认命令或参数,如果用户在 docker run 时指定了其他命令,则 CMD 会被覆盖。CMD 可以设置为 exec 形式或 shell 形式,用于定义容器的默认执行行为。
- 【回答框架 2】ENTRYPOINT 指令设置容器启动时固定的主命令,通常不会被 docker run 后附加的命令直接覆盖,而是将这些附加命令作为参数传递给 ENTRYPOINT。这使容器行为更可控,适合固定入口的场景。
- 【回答框架 3】两者可以组合使用:ENTRYPOINT 指定固定主命令,CMD 提供默认参数,用户可在运行 docker run 时覆盖 CMD 部分,从而实现灵活性与固定入口的平衡。
- 【回答框架 4】当只使用 CMD 时,适合提供完全可覆盖的默认命令;当需要强制容器执行特定程序时,应优先使用 ENTRYPOINT,尤其是以脚本作为入口或需要处理参数传递的情况。
- 【回答框架 5】使用 exec 形式(JSON 数组)时不会经过 shell 处理,可避免信号转发问题,而 shell 形式会启动 shell 进程,需要注意 PID 1 与信号处理的差异。
- 【关键点 1】CMD 提供默认命令并可通过 docker run 覆盖,ENTRYPOINT 定义固定入口且可接收参数。
- 【关键点 2】组合使用时,CMD 作为默认参数被传递给 ENTRYPOINT,用户可覆盖 CMD 部分。
- 【关键点 3】exec 形式不经过 shell,便于信号转发;shell 形式会引入 shell 进程,可能影响信号处理。
- 【易错点 1】不要将 CMD 和 ENTRYPOINT 都设置为完全独立的命令而不考虑覆盖机制,以免出现行为混淆。
- 【易错点 2】使用 shell 形式时要注意 PID 1 不是最终应用进程,可能导致容器无法正确响应 SIGTERM。
- 【易错点 3】未区分 exec 与 shell 形式而直接使用字符串命令,可能不会按预期执行,因为 exec 形式要求 JSON 数组。