入口与默认命令的组合
镜像的启动行为由两个声明共同决定:一个固定要执行的程序,一个是默认参数或默认命令。理解它们的覆盖规则是用好镜像的前提:运行时给的内容到底替换了哪一部分,取决于镜像里同时声明了什么,而不是凭感觉猜。
基本信息
| 两个声明 | 入口程序负责固定执行什么,默认命令负责默认参数或默认行为 |
|---|---|
| 覆盖来源 | 运行命令里的参数、覆盖入口的选项 |
| 生效规则 | 运行时给的命令替换默认命令,覆盖入口时替换入口程序 |
| 多条声明 | 各自只有最后一条生效 |
| 推荐形式 | 两者都建议用参数数组形式,参数与信号处理更可控 |
典型使用场景
- 工具型镜像:固定入口程序,运行时用参数控制行为
- 服务型镜像:默认命令给出常规启动方式,特殊环境运行时替换
- 多模式镜像:同一镜像通过参数以不同角色运行,减少镜像数量
- 调试镜像:平时按默认方式启动,排查时覆盖入口换成 shell
- 交付给他人使用:入口固定、参数可覆盖的设计对使用者最友好
典型声明与运行效果
典型声明与运行效果
ENTRYPOINT ["/app/server"] # 固定入口程序
CMD ["--port", "8080", "--log", "stdout"] # 默认参数,可被替换
# 只给镜像名:入口加默认参数
# docker run app/api:1.0
# 追加参数:入口加新参数
# docker run app/api:1.0 --port 9090
# 覆盖入口:新程序加原默认参数
# docker run --entrypoint /bin/sh app/api:1.0覆盖规则速查
| 运行方式 | 实际执行 | 常见误区 |
|---|---|---|
| 只给镜像名 | 入口程序加默认参数 | 以为默认命令会独立执行 |
| 镜像名后跟参数 | 入口程序加新参数 | 以为参数会追加而不是替换 |
| 覆盖入口不给参数 | 新程序加原默认参数 | 忽略原默认参数仍会传入 |
| 覆盖入口并给参数 | 新程序加新参数 | 调试后忘记恢复原入口 |
| 镜像只有默认命令 | 运行时给的命令整体替换它 | 以为替换只影响参数部分 |
设计镜像时的选择
- 希望使用者只能追加参数时,用固定入口加默认参数的模式
- 希望使用者能整体替换启动方式时,只用默认命令即可
- 需要复杂初始化时,用入口脚本完成准备后再交给服务进程
- 同镜像多角色时,用参数区分角色,避免维护多份构建描述
- 对外交付的镜像在文档里写清覆盖规则,减少使用者试错
运行时追加的参数只给入口程序,不会给默认命令。想改变默认参数的具体取值,要么整段替换,要么在入口脚本里做参数解析。
两个声明各自重复出现时只有最后一条生效。写完构建描述后查看镜像配置里的最终值,比对照文件内容可靠。