Docker ENTRYPOINT无法执行命令求助:OCI runtime报错排查
你遇到的问题核心是ENTRYPOINT的exec格式(JSON数组)使用错误,我来给你拆解清楚:
为什么之前的配置会报错?
当你用ENTRYPOINT ["bash -c tox -e docker-server"]这种写法时,Docker会把整个字符串bash -c tox -e docker-server当作一个单独的可执行文件路径去查找,而不是把它拆分成bash(可执行文件)和后续的参数-c、tox -e docker-server。系统里显然没有叫这个长名字的可执行文件,所以就会报"executable file not found in $PATH"的错误。
同理,ENTRYPOINT ["sh ls -l"]也是一样的问题,Docker在找一个叫sh ls -l的可执行文件,自然找不到。
正确的配置方式
方式1:使用exec格式(推荐)
把命令的每个部分拆成JSON数组的独立元素,让Docker明确区分可执行文件和它的参数:
# 执行 tox 命令的正确写法 ENTRYPOINT ["bash", "-c", "tox -e docker-server"] # 执行 ls -l 的正确写法 ENTRYPOINT ["sh", "-c", "ls -l"]
这里bash/sh是可执行文件,-c是告诉shell执行后面的字符串命令,最后一个元素是你实际要运行的命令内容。这种方式的好处是,你的命令会成为容器的PID 1进程,能正确接收信号(比如docker stop发送的SIGTERM),适合生产环境。
方式2:使用shell格式(不推荐生产环境)
如果你不想用数组格式,可以直接写shell命令,Docker会自动用/bin/sh -c来包裹执行:
ENTRYPOINT bash -c tox -e docker-server ENTRYPOINT sh -c ls -l
但这种方式下,你的命令是在shell子进程里运行的,PID 1是shell进程,当你执行docker stop时,信号会被shell吃掉,可能导致容器无法优雅停止,所以生产环境更推荐用exec格式。
快速验证方法
你可以用docker run --entrypoint临时替换命令来测试镜像环境是否正常:
# 测试 ls -l 是否能正常执行 docker run --entrypoint sh your-image-name -c "ls -l"
如果这个命令能正常输出,说明你的镜像里有sh且路径正确,那把ENTRYPOINT改成正确的数组格式就没问题了。
内容的提问来源于stack exchange,提问作者Fact

