ENTRYPOINT 与 CMD 区别
ENTRYPOINT 和 CMD 都用于定义容器启动命令,但职责不同,下面梳理其区别与配合。
CMD 指令
默认启动命令
dockerfile
# CMD 定义默认启动命令
CMD ["nginx", "-g", "daemon off;"]
# 可被 docker run 覆盖
docker run my-image custom-command # custom-command 替换 CMD
三种格式
dockerfile
# Exec 格式(推荐)
CMD ["executable", "param1", "param2"]
# Shell 格式
CMD command param1 param2
# 作为 ENTRYPOINT 的默认参数
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
Shell 格式会启动 shell 进程:
/bin/sh -c "command",Exec 格式直接执行程序。
ENTRYPOINT 指令
固定执行程序
dockerfile
# ENTRYPOINT 设置固定执行程序
ENTRYPOINT ["nginx"]
# docker run 追加参数
docker run my-image -v # 执行: nginx -v
docker run my-image -t # 执行: nginx -t
不可被覆盖
dockerfile
ENTRYPOINT ["nginx", "-g", "daemon off;"]
# docker run 后追加命令会被追加,不是替换
docker run my-image -t # 执行: nginx -g 'daemon off;' -t
配合使用(推荐)
dockerfile
# ENTRYPOINT 固定程序,CMD 提供默认参数
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
# 默认启动:nginx -g 'daemon off;'
docker run my-image
# 覆盖 CMD:nginx -t
docker run my-image -t
# 覆盖 CMD:nginx -v
docker run my-image -v
对比表格
| 对比项 | ENTRYPOINT | CMD |
|---|---|---|
| 作用 | 固定执行程序 | 默认参数/命令 |
| 可被覆盖 | ❌ | ✅ |
| docker run 后 | 追加为参数 | 完整替换 |
| 数量 | 仅最后一条生效 | 仅最后一条生效 |
| 推荐用法 | 与 CMD 配合 | 单独使用或配合 |
Shell vs Exec 格式
dockerfile
# Exec 格式(推荐)
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
# Shell 格式(不推荐)
ENTRYPOINT nginx
CMD nginx -g 'daemon off;'
# Shell 格式问题:
# 1. 多一层 shell 进程
# 2. 信号处理不正确(SIGTERM 无法终止)
# 3. 环境变量不展开
实用示例
Nginx 镜像
dockerfile
FROM nginx:alpine
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
# 使用
docker run my-nginx # nginx -g 'daemon off;'
docker run my-nginx -t # nginx -t
docker run my-nginx -s reload # nginx -s reload
自定义脚本
dockerfile
FROM ubuntu:22.04
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["default-arg"]
entrypoint.sh:
Bash
#!/bin/bash
echo "Starting with args: $@"
exec "$@"
信号处理
dockerfile
# 错误:Shell 格式,SIGTERM 发给 shell 不是发给 nginx
ENTRYPOINT nginx -g 'daemon off;'
# 正确:Exec 格式,SIGTERM 直接发给 nginx
ENTRYPOINT ["nginx", "-g", "daemon off;"]
# 或使用 tini 处理信号
ENTRYPOINT ["tini", "--", "nginx", "-g", "daemon off;"]
信号处理对优雅停机很重要,Shell 格式会导致 SIGTERM 无法正确传递给子进程。
要点总结
- ENTRYPOINT 设置固定执行程序,CMD 提供默认参数
- CMD 可被 docker run 覆盖,ENTRYPOINT 不可
- 推荐配合使用:ENTRYPOINT 定义程序,CMD 定义默认参数
- 优先使用 Exec 格式,避免 Shell 格式的信号处理问题
- Shell 格式启动
/bin/sh -c,Exec 格式直接执行程序
📝 发现内容有误?点击此处直接编辑