ENTRYPOINT 并非完全不可变,其行为取决于 shell 或 exec 形式:shell 形式忽略 CMD 且不可覆盖;exec 形式下 CMD 提供默认参数,docker run 参数会替换 CMD;需配合 CMD 才能实现可定制入口;彻底禁用覆盖须用脚本封装校验;ENTRYPOINT 不影响 docker exec。

ENTRYPOINT 指令确实用于固定容器启动时执行的程序,但它不是“完全不可变”的——它的行为取决于写法(shell 形式或 exec 形式)以及是否配合 CMD 使用。
ENTRYPOINT 的两种写法决定灵活性
Shell 形式(如 ENTRYPOINT nginx -g "daemon off;")会将命令包裹在 /bin/sh -c 中运行,此时 CMD 会被忽略(除非你手动拼接),且无法被 docker run 的参数覆盖。
Exec 形式(如 ENTRYPOINT ["nginx", "-g", "daemon off;"])更推荐,它直接执行指定程序,CMD 的内容会作为默认参数追加到 ENTRYPOINT 后面;同时,docker run 后跟的参数会**替换掉 CMD**,而不是追加——这是实现可定制入口的关键。
与 CMD 配合才能发挥最大作用
- 如果只写 ENTRYPOINT(exec 形式),没写 CMD,那么 docker run 后的参数会原样传给 ENTRYPOINT 程序
- 如果写了 ENTRYPOINT + CMD(都用 exec 形式),CMD 提供默认参数,而
docker run image arg1 arg2会用arg1 arg2替换 CMD,最终执行的是[ENTRYPOINT] [arg1 arg2] - 例如:
ENTRYPOINT ["python", "app.py"]CMD ["--port", "8000"]
运行docker run myimg --port 8080→ 实际执行python app.py --port 8080
想彻底禁止覆盖?得靠脚本封装
单纯靠 ENTRYPOINT 无法绝对阻止用户传参——只要用 exec 形式,docker run 的参数总能抵达。若需强制固定启动逻辑(比如只允许运行某个服务、拒绝任意命令),常见做法是:
- 写一个 shell 脚本(如
entrypoint.sh),在里面校验参数、设置环境、然后调用主程序 - 用
ENTRYPOINT ["./entrypoint.sh"]固定入口 - 在脚本中忽略或拒绝非预期参数,甚至直接 exit 1
注意:ENTRYPOINT 不影响 docker exec
ENTRYPOINT 只控制 docker run 初始化容器时的主进程。后续用 docker exec -it container /bin/sh 进入容器,执行的是你指定的命令,和 ENTRYPOINT 无关——它不接管交互式会话。










