You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Docker Swarm的/bin/sh中正确使用exec "$@"启动容器进程?

问题分析与解决

你的问题核心是ENTRYPOINT和CMD的配置逻辑错误,导致entrypoint.sh里的exec "$@"没有接收到任何可执行的命令参数,容器自然会因无进程运行而退出。

错误原因

当前Dockerfile的配置是:

ENTRYPOINT ["/bin/sh"]
CMD ["entrypoint.sh"]

这会让容器启动时执行/bin/sh entrypoint.sh——此时entrypoint.sh作为sh的参数被调用,但你没有给entrypoint.sh传递任何后续参数,所以脚本里的$@是空值,exec "$@"相当于执行空命令,容器直接退出。

正确配置方案

方案一:直接将entrypoint.sh设为ENTRYPOINT(推荐)

修改Dockerfile的ENTRYPOINT和CMD,让entrypoint脚本作为入口,CMD提供默认的启动命令(即openresty的nginx启动命令):

FROM openresty/openresty:alpine-fat

WORKDIR /

COPY entrypoint.sh entrypoint.sh

RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

这样容器启动时,会执行/entrypoint.sh nginx -g 'daemon off;',脚本里的exec "$@"会替换当前进程为nginx -g 'daemon off;',既实现了你想要的exec传递信号的效果,也能正常启动openresty进程。

方案二:保留/bin/sh作为ENTRYPOINT(不推荐)

如果一定要通过sh调用脚本,需要用-c参数传递完整命令链,让$@能拿到后续参数:

FROM openresty/openresty:alpine-fat

WORKDIR /

COPY entrypoint.sh entrypoint.sh

RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/bin/sh", "-c"]
CMD ["/entrypoint.sh nginx -g 'daemon off;'"]

这种方式绕了一层shell,不如方案一直接,且可能影响信号传递的可靠性。

额外说明

exec "$@"的核心作用是让实际运行的进程替换entrypoint脚本的进程,这样容器的主进程就是业务进程(比如nginx),外部发送的停止信号(如SIGTERM)能直接传递给它,避免僵尸进程问题。

内容的提问来源于stack exchange,提问作者SapphireBlazer01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:12:37