ENTRYPOINT 实现参数化 CLI 工具,主命令固定(如 ["curl", "-m", "10"]),CMD 仅提供默认参数(如 ["https://httpbin.org/get"]),运行时传参可覆盖 CMD;推荐 exec 形式以支持信号传递和参数透传。

Dockerfile 中的 ENTRYPOINT 是实现参数化命令行工具的关键,它能让容器像本地可执行程序一样被调用,同时支持传入动态参数。
ENTRYPOINT 与 CMD 的协作机制
ENTRYPOINT 定义容器启动时**始终执行的主命令**,而 CMD 提供其**默认参数**。当运行容器时传入参数(如 docker run mytool --help),这些参数会追加到 ENTRYPOINT 后面,覆盖 CMD 的默认值。
- 推荐使用 exec 形式:
ENTRYPOINT ["node", "app.js"],避免 shell 解析带来的变量和信号问题 -
CMD应只写参数,例如CMD ["--port", "3000"],不写命令本身 - 若用 shell 形式(
ENTRYPOINT node app.js),则无法接收外部参数——它会被整个当作 shell 命令执行,忽略后续参数
构建一个可复用的 CLI 工具镜像
以封装 curl 为例,制作一个带预设超时和 User-Agent 的 HTTP 工具:
FROM curlimages/curl:8.9.1 ENTRYPOINT ["curl", "-m", "10", "-A", "my-cli/1.0"] CMD ["https://httpbin.org/get"]
构建后可直接使用:
-
docker run http-tool https://example.com→ 使用自定义 URL 替换默认地址 -
docker run http-tool -I https://example.com→ 加入-I参数获取响应头 -
docker run --rm -v $(pwd):/data http-tool -o /data/out.html https://example.com→ 结合挂载和额外选项
支持多子命令的进阶用法
当工具需支持类似 git commit、git push 的子命令时,可将入口设为包装脚本:
COPY entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"]
entrypoint.sh 内容示例:
#!/bin/sh case "$1" in fetch) exec git fetch "$@" ;; log) exec git log --oneline "$@" ;; *) exec git "$@" ;; esac
- 用
exec替换当前 shell 进程,确保信号(如 Ctrl+C)能正确传递给子命令 - 保持参数透传,用户操作体验与原生 CLI 一致
- 适合封装 git、jq、ffmpeg 等已有工具,添加默认配置或权限控制
调试与验证技巧
确认 ENTRYPOINT 行为是否符合预期:
- 用
docker inspect myimage | jq '.[0].Config.Entrypoint'查看解析后的入口数组 - 临时绕过 ENTRYPOINT:
docker run --entrypoint sh myimage -c 'echo $0 $@' arg1 arg2 - 在容器内执行
ps aux,观察实际启动的进程是否为预期命令(而非 /bin/sh)

















