ChatGPT解决这个技术问题 Extra ChatGPT

docker:在 $PATH 中找不到可执行文件

我有一个安装 grunt 的 docker 映像,但是当我尝试运行它时,出现错误:

Error response from daemon: Cannot start container foo_1: \
    exec: "grunt serve": executable file not found in $PATH

如果我在交互模式下运行 bash,则 grunt 可用。

我究竟做错了什么?

这是我的 Dockerfile:

# https://registry.hub.docker.com/u/dockerfile/nodejs/ (builds on ubuntu:14.04)
FROM dockerfile/nodejs

MAINTAINER My Name, me@email.com

ENV HOME /home/web
WORKDIR /home/web/site

RUN useradd web -d /home/web -s /bin/bash -m

RUN npm install -g grunt-cli
RUN npm install -g bower

RUN chown -R web:web /home/web
USER web

RUN git clone https://github.com/repo/site /home/web/site

RUN npm install
RUN bower install --config.interactive=false --allow-root

ENV NODE_ENV development

# Port 9000 for server
# Port 35729 for livereload
EXPOSE 9000 35729
CMD ["grunt"]
您可以尝试使用 CMD grunt 构建 docker 吗?或者您可以尝试通过传递完整路径来执行 grunt 命令?
@mark91 请您详细说明您要求使用 CMD grunt? 重新构建您的意思是删除 [""] 吗?
刚刚试了一下——它奏效了——谢谢!因此,对于其他进入的人,将 CMD ["grunt"] 更改为 CMD grunt
这是因为如果您执行 CMD ["grunt"],您将使用另一个 shell 来执行命令,因此在该 shell 中可能不会设置 $PATH。

K
Kabir Sarin

这是我粘贴错误消息时谷歌上的第一个结果,这是因为我的论点有问题。

容器名称必须在所有参数之后。

坏的:

docker run <container_name> -v $(pwd):/src -it

好的:

docker run -v $(pwd):/src -it <container_name>

如果您在开始编码之前总是仔细阅读文档,那么您将永远无法完成任何事情。当您购买新车时,您是否在开车回家之前阅读了 200 页的说明书?没有。当你的车出现问题时,你是先用谷歌搜索,还是去拿手册?这是完全合理的,我只能想象所有发现它有用但没有点击upvote按钮的人!有点不合理的是,这个完全不相关的答案是这个错误消息的第一个谷歌结果,或者 docker cli 不直观且无情。干杯。
在许多脚本中,标志的顺序并不重要,所以我明白为什么这会发生在任何人身上。答案很有帮助。不用说,来自 docker 的错误消息根本没有用。
哇,如果不是这个答案,我会挣扎一段时间。为什么 UNIX 还没有一个标准的、灵活的和强大的 CLI 参数解析器?...
我被接受的答案误导了,想自己写,但似乎已经在这里了。所以我可以确认这解决了问题......
这是问题的核心
A
Amin Shojaei

当您对命令使用 exec 格式时(例如,CMD ["grunt"],一个带双引号的 JSON 数组),它将在 没有 shell 的情况下执行。这意味着大多数环境变量将不存在。

如果您将命令指定为常规字符串(例如 CMD grunt),则 CMD 之后的字符串将与 /bin/sh -c 一起执行。

Dockerfile reference 的 CMD 部分提供了有关这方面的更多信息。


这是参考 docs.docker.com/engine/reference/builder/#cmd 的 CMD 部分的链接
原谅这个愚蠢的问题,但是你怎么能在没有 shell 的情况下执行 linux 命令呢?在 linux 机器(不使用 docker)上执行此操作等效于什么?
要回答我自己的问题,它类似于做 sudo set(exec set)。这些将失败,因为它们在没有 shell 的情况下执行命令(并且 set 是内置的 shell)。但是,sudo ls(exec ls) 将起作用,因为 ls 是实际的二进制文件 /bin/ls
哇,太简单了,我一直在努力解决这个问题,太愚蠢了,谢谢!
r
rlandster

我发现了同样的问题。我做了以下事情:

docker run -ti devops -v /tmp:/tmp /bin/bash

当我将其更改为

docker run -ti -v /tmp:/tmp devops /bin/bash

它工作正常。


它对我有用,但我不明白这里 -v 的用法。 -v是绑定挂载一个卷(如docker run --help | grep "\-v"中所述),对我来说,我已经在File Sharing(Docker设置)中挂载了/tmp,为什么还要再次使用它呢?
B
Ben Creasy

像这样的错误有几个可能的原因。

在我的情况下,这是由于可执行文件(来自 Ghost blog Dockerfiledocker-entrypoint.sh)在我下载后缺少可执行文件模式。

解决方案:chmod +x docker-entrypoint.sh


这是指出我正确答案的评论。我不得不复制文件然后chmod它。
b
beyondtheteal

出于某种原因,除非我添加“bash”澄清器,否则我会收到该错误。即使在我的入口点文件顶部添加“#!/bin/bash”也无济于事。

ENTRYPOINT [ "bash", "entrypoint.sh" ]

@SteveLorimer,是的。我在入口点调用之前做了一个 COPY,然后是 RUN chmod +x /compile_nibbler.sh
我使用的是 python alpine 图像,因此适用的命令是 ENTRYPOINT [ "sh", "entrypoint.sh" ]
s
schnatterer

一个 Docker 容器可以在没有外壳的情况下构建(例如 https://github.com/fluent/fluent-bit-docker-image/issues/19)。

在这种情况下,您可以复制一个静态编译的 shell 并执行它,例如

docker create --name temp-busybox busybox:1.31.0
docker cp temp-busybox:/bin/busybox busybox
docker cp busybox mycontainerid:/busybox
docker exec -it mycontainerid /bin/busybox sh

P
Parsa

我有同样的问题,经过大量的谷歌搜索,我无法找到如何解决它。

突然我注意到我的愚蠢错误:)

As mentioned in the docsdocker run 的最后一部分是加载容器后要运行的命令及其参数。

不是容器名称!!!

那是我尴尬的错误。

下面我为您提供了我的命令行图片,以查看我做错了什么。

这就是 docs 中提到的修复。

https://i.stack.imgur.com/uNQQ2.jpg


B
BMitch

在显示的错误消息中:

来自守护程序的错误响应:无法启动容器 foo_1:\ exec:“grunt serve”:$PATH 中找不到可执行文件

它抱怨它找不到可执行文件 grunt serve,而不是它找不到带有参数 serve 的可执行文件 grunt。对该特定错误最可能的解释是使用 json 语法运行命令:

[ "grunt serve" ]

在您的撰写文件中。这是无效的,因为 json 语法要求您拆分每个参数,这些参数通常会由 shell 在每个空间上为您拆分。例如:

[ "grunt", "serve" ]

您可以将这两者都放入单个参数的另一种可能方法是,如果您要在 docker run 命令中将它们引用到单个 arg 中,例如

docker run your_image_name "grunt serve"

在这种情况下,您需要删除引号,以便将其作为单独的参数传递给运行命令:

docker run your_image_name grunt serve

对于看到这一点的其他人,executable file not found 意味着 Linux 看不到您尝试在容器中运行的具有默认 $PATH 值的二进制文件。这可能意味着很多可能的原因,这里有一些:

您还记得在图像中包含二进制文件吗?如果您运行多阶段映像,请确保在最后阶段运行二进制安装。使用交互式 shell 运行您的图像并验证它是否存在: docker run -it --rm your_image_name /bin/sh

您在进入容器时的路径可能会针对交互式 shell 进行修改,特别是如果您使用 bash,因此您可能需要指定容器内二进制文件的完整路径,或者您可能需要使用以下命令更新 Dockerfile 中的路径: ENV PATH=$PATH:/custom/dir/bin

二进制文件可能没有设置执行位,因此您可能需要使其可执行。使用 chmod 执行此操作: RUN chmod 755 /custom/dir/bin/executable

二进制文件可能包含映像中不存在的动态链接库。您可以使用 ldd 查看动态链接库的列表。一个常见的原因是使用 glibc(大多数 Linux 环境)编译并使用 musl(由 Alpine 提供)运行:ldd /path/to/executable

如果您使用卷运行映像,则该卷可以覆盖映像中可执行文件所在的目录。卷不会与映像合并,它们会像任何其他 Linux 文件系统挂载一样挂载在文件系统树中。这意味着挂载点的父文件系统中的文件不再可见。 (请注意,命名卷是由 docker 从映像内容中初始化的,但这仅在命名卷为空时发生。)因此,解决方法是不要将卷安装在您想要从映像运行的可执行文件的路径之上。

如果您为不同的平台运行二进制文件,并且没有使用 --fix-binary 选项配置 binfmt_misc,qemu 将在容器文件系统命名空间而不是主机文件系统中寻找解释器。有关此问题的更多详细信息,请参阅此 Ubuntu 错误报告。

如果错误来自 shell 脚本,则问题通常出在该脚本的第一行(例如 #!/bin/bash)。由于上述原因,该命令在图像中不存在,或者该文件未使用 Linux 换行符保存为 ascii 或 utf8。你可以尝试 dos2unix 来修复换行,或者检查你的 git 和编辑器设置。


L
Lakshmanavaradhan

问题是 glibc,它不是 apline base iamge 的一部分。

添加后它对我有用:)

以下是获取 glibc 的步骤

apk --no-cache add ca-certificates wget
wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk
apk add glibc-2.28-r0.apk

M
Muhammad Faizan Fareed

我在构建高山基础映像时收到此错误消息:

ERROR: for web  Cannot start service web: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "bash": executable file not found in $PATH: unknown

在我的 docker-compose 文件中,我有命令指令,其中使用 bash 执行命令,而 bash 不附带 alpine 基本映像。

command: bash -c "python manage.py runserver 0.0.0.0:8000"

然后我使用 sh (shell) 实现并执行了命令。它对我有用。


J
Jon

参考标题。

我的错误是在 docker run 期间通过 --env-file 放置变量。其中,该文件包含一个 PATH 扩展名:PATH=$PATH:something,这导致 PATH var 看起来像 PATH=$PATH:something(未执行 var 解析)而不是 PATH:/usr/bin...:something

我无法通过 --env-file 进行解析,因此我看到此问题的唯一方法是在 Dockerfile 中使用 ENV


V
Vito

我使用 docker-compose 遇到了这个问题。此处或 this related question 上的解决方案均未解决我的问题。最终对我有用的是使用 docker prune -a 清除所有缓存的 docker 工件并重新启动 docker。


v
vacavaca

要使其工作,请添加对 /usr/bin 的软引用:

ln -s $(哪个节点) /usr/bin/node

ln -s $(哪个 npm) /usr/bin/npm


请添加有关它将如何帮助他的描述。