exec格式是run、cmd、entrypoint的推荐写法,其核心特点是不经过shell解析、直接执行可执行文件,提升安全性与信号传递可靠性;run用于构建时执行命令,cmd设默认启动命令(可被覆盖),entrypoint设主程序入口(常与cmd配合提供参数)。

Docker 镜像构建中,RUN、CMD、ENTRYPOINT 这三条指令都支持 Exec 格式(也叫 JSON 数组格式),它的核心特点是:不经过 shell 解析,直接执行可执行文件,更安全、更可控,也是官方推荐的写法。
RUN 指令的 Exec 格式
用于在构建镜像时执行命令,适合需要明确指定解释器或避免 shell 特性干扰的场景。
RUN ["executable", "param1", "param2"]
✅ 正确示例:
RUN ["/bin/bash", "-c", "echo 'hello' > /tmp/greeting.txt"] RUN ["apt-get", "update"] RUN ["apk", "add", "--no-cache", "curl"]
⚠️ 注意:
- 第一个元素必须是绝对路径的可执行文件(如
/bin/bash、/usr/bin/apt-get); - 不会自动调用
/bin/sh -c,所以不能写RUN ["echo hello"](echo不是独立可执行文件路径,且没指定解释器); - 如果要用 shell 功能(比如管道
|、重定向>、变量$HOME),必须显式调用 shell,例如:RUN ["/bin/sh", "-c", "ls /app | grep .py > /tmp/list.txt"]
CMD 指令的 Exec 格式
定义容器启动时默认执行的命令(可被 docker run 后的参数覆盖)。
CMD ["executable", "param1", "param2"]
✅ 推荐写法(安全、明确):
CMD ["nginx", "-g", "daemon off;"] CMD ["python", "app.py"] CMD ["java", "-jar", "/app.jar"]
❌ 避免这样写(shell 格式,隐式调用 /bin/sh -c):
CMD python app.py # 实际执行的是 /bin/sh -c "python app.py"
ENTRYPOINT 指令的 Exec 格式
用于设置容器的“主程序”,让容器表现得更像一个可执行命令。常与 CMD 配合使用。
ENTRYPOINT ["executable", "param1", "param2"]
✅ 典型组合(ENTRYPOINT 定义主程序,CMD 提供默认参数):
FROM alpine ENTRYPOINT ["/bin/sh", "-c"] CMD ["echo 'Hello from Docker'"]
运行 docker run myimage → 输出 Hello from Docker
运行 docker run myimage "echo 'Hi there'" → 输出 Hi there
✅ 更实用的例子(封装工具镜像):
FROM ubuntu:22.04 COPY ./myscript.sh /usr/local/bin/myscript RUN chmod +x /usr/local/bin/myscript ENTRYPOINT ["myscript"]
这样 docker run myimage --help 就会把 --help 传给 myscript 执行。
小贴士:Exec 格式 vs Shell 格式对比
| 特性 | Exec 格式 | Shell 格式 |
|---|---|---|
| 写法 | ["cmd", "arg1", "arg2"] |
cmd arg1 arg2 |
| 启动方式 | 直接 exec 系统调用 | 调用 /bin/sh -c "cmd arg1 arg2"
|
| PID 1 | 是真正的主进程(利于信号传递) |
/bin/sh 是 PID 1,你的命令是子进程 |
| 变量/管道/重定向 | ❌ 不支持(除非显式调用 shell) | ✅ 原生支持 |
| 安全性 | ✅ 更高(无 shell 注入风险) | ⚠️ 存在注入隐患(尤其含变量时) |
不复杂但容易忽略











