【问题标题】:standard_init_linux.go:190: exec user process caused "no such file or directory" - Dockerstandard_init_linux.go:190: exec 用户进程导致“没有这样的文件或目录” - Docker
【发布时间】:2019-01-01 15:19:33
【问题描述】:

当我在 Windows 10 上运行我的 docker 映像时。我收到此错误:

standard_init_linux.go:190: exec user process caused "no such file or directory"

我的 docker 文件是:

FROM openjdk:8

EXPOSE 8080

VOLUME /tmp

ADD appagent.tar.gz /opt/app-agent
ADD services.jar app.jar
ADD run.sh /run.sh

# Install compiler and perl stuff
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y gcc-multilib
RUN apt-get install -y perl

# Install Percona Toolkit
RUN apt-get install --yes percona-toolkit
RUN ["chmod", "+x", "/run.sh"]
ENTRYPOINT ["/run.sh"]

脚本以 #!/bin/sh

开头
#!/bin/sh
set -e

JAVA_OPTS="-Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/urandom"

if [ "${APPD_APP_NAME}" != "" ]; then
JAVA_AGENT="-javaagent:/opt/app-agent/javaagent.jar
fi

exec java ${JVM_OPTS} ${JAVA_OPTS} ${JAVA_AGENT} -jar /app.jar

试过的方法1: 尝试将 #!/bin/sh 更改为 #!/bin/bash,但出现同样的错误。

试过的方法2: 在 docker 文件中添加了 dos2unix

RUN apt-get install -y dos2unix
RUN dos2unix /run.sh

【问题讨论】:

    标签: docker dockerfile docker-for-windows


    【解决方案1】:

    我正在构建一个 Go 应用程序,这些答案对我来说都是错误的,所以我想分享我的解决方案。对我来说,我有一个不涉及 Windows 的 Dockerfile(在 Mac 上编码,尽管在 macOS 11 上的一个和 macOS 12 上的另一个之间共享。但行结尾是相同的)。

    对我来说,最终的解决方案是我需要将我的应用程序构建为一个静态链接的二进制文件,它可以在没有外部依赖项的情况下运行。我正在为一个 Go 应用程序构建一个 Dockerfile,该应用程序首先在 Go 构建器映像中构建,然后在临时映像中构建。为了让我的二进制文件能够从头开始运行,我必须添加 CGO_ENABLED=0 标志。此 reddit 页面上的更多信息:https://www.reddit.com/r/golang/comments/pi97sp/comment/hbo0fq6/?utm_source=share&utm_medium=web2x&context=3

    我的代码,最终运行:

    ############################
    # STEP 1 build optimized executable binary
    ############################
    FROM golang:1.16-alpine AS builder
    
    WORKDIR /app
    
    COPY go.mod ./
    COPY go.sum ./
    RUN go mod download
    
    COPY *.go ./
    
    RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o cl-api
    
    ############################
    # STEP 2 build a small image
    ############################
    FROM scratch
    
    COPY --from=builder /app/cl-api /
    
    EXPOSE 8000
    
    ENTRYPOINT ["/cl-api"]
    
    

    【讨论】:

      【解决方案2】:

      如果尝试在从头开始的容器中运行动态链接的可执行文件,也会出现此错误。可执行文件将无法链接到共享 (so) 库,并会报告(信息量不大)“没有这样的文件或目录”错误。

      让我们构建一个动态可执行文件test:

      cat <<EOF | g++ -x c++ - -o test
      #include <iostream>
      int main() {
          std::cerr << "Hello!" << std::endl;
          return 0;
      }
      EOF
      

      这确实是一个动态的可执行文件。运行 ldd test 将报告类似(依赖于 libc 等):

      linux-vdso.so.1 (0x00007ffd699fc000)
      libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff570f7a000)
      libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff570c76000)
      libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff570a5f000)
      libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff5706c0000)
      /lib64/ld-linux-x86-64.so.2 (0x00007ff5714fe000)
      

      现在,让我们使用以前的可执行文件从头开始构建映像。 Dockerfile 将是:

      FROM scratch
      COPY test /
      CMD [ "/test" ]
      

      构建图像。然后,从镜像运行一个即时容器:

      docker build . -t local/test
      docker run --rm local/test
      

      容器失败,退出代码为 1,我得到:

      standard_init_linux.go:219: exec user process caused: no such file or directory
      

      通过使用静态链接(在之前的gcc/g++ 链接器命令中使用-static 标志)解决了这个问题,它产生了一个独立的可执行文件。

      【讨论】:

        【解决方案3】:

        问题:

        问题来自 .sh 文件。首先我们必须记住 Windows 使用 \r\n 作为行尾,而 Linux 和 Mac 使用 \n。 Git 有一个名为 autoclrf 的功能,在 Windows 上通常设置为“true”。这会在从 Git 存储库完成下载后自动将 \n 转换为 \r\n,但 Git 不会对此做出任何通知,因此错误是生成。这个过程是好的,至少对于其他文件来说是这样,但对于 bash 文件就不是这样了,entrypoint.sh 文件就是这样。

        即时解决方案:

        打开您喜欢的代码编辑器并更改导致冲突的文件的行尾,在我们的例子中:entrypoint.sh .您可以在软件右下角的 Visual Studio Code 中执行此操作,单击 CRLF 并将文件行尾更改为 LF。。 p>

        从下面的链接阅读永久解决方案的整篇文章:

        https://davidcasr.medium.com/docker-standard-init-linux-go-211-exec-user-process-caused-no-such-file-or-directory-en-c0cb42edb295

        【讨论】:

          【解决方案4】:
          git config core.autocrlf false  
          git rm --cached -r .   
          git reset --hard
          

          https://www.codegrepper.com/code-examples/shell/How+to+change+all+files%27+default+eol+to+LF+in+windows

          【讨论】:

            【解决方案5】:

            使用notepad++,进入编辑->EOL转换->从CRLF改成LF。

            更新:对于 VScode 用户:您可以通过单击状态栏右下方的 CRLF 将 CRLF 更改为 LF

            【讨论】:

            • 完美!我添加了一个 .sh 文件,该文件正在从我的 Dockerfile 运行。我替换了行尾和Ta Da。谢谢
            • 我在 notepad++ 的“编辑选项卡”中没有找到这个选项,但我已经更改了它,点击右下角的 Windows(CR LF)按钮,然后我更改为 Unix。非常感谢!
            • 尝试在 Windows 上构建和运行 ckan docker 映像时出现此错误。如果您在克隆的 repo 上遇到此问题,在克隆期间使用 core.autocrlf 设置可能会很有用,如果是,请执行:git config core.autocrlf input =&gt; (deleted the files from the repo; wasn't sure if git reset would reset the newlines) =&gt; git reset --hard 复制自:github.com/LiveOverflow/PwnAdventure3/issues/11
            • 你可以在 VS Code 中找到设置,也可以在右下角找到
            • 挣扎了几个小时...感谢 Vikas 节省了我的时间
            【解决方案6】:

            我只是想补充一点:对于VSCode用户,你可以通过点击状态栏中的CRLF,然后选择LF来将CRLF换行符改为LF 并保存文件。

            我有同样的问题,这解决了它。

            【讨论】:

            • 为我工作,用于在 Windows 上运行使用在 Linux 上创建的 docker-compose 的节点 alpine 容器。谢谢!
            【解决方案7】:

            您可以在 Mac 上使用 BBEdit 来解决此问题,因为 Notepad++ 不可用。

            在窗口底部很明显。除了字符集选项

            【讨论】:

              【解决方案8】:

              我的.sh 文件末尾多了一行。我删除了它并解决了这个问题。

              【讨论】:

                【解决方案9】:

                对于 VScode 用户,您可以在 IDE 的右下角找到 CRLF/LF,因此将其切换到 LF 并再次保存您的文件。多田!!你会没事的。

                【讨论】:

                  【解决方案10】:

                  我解决了一个类似的问题

                  我的配置: -> Docker 桌面 WSL 2 后端 - Windows -> 需要 CGO_ENABLED=1,因为我使用 Lib 编译了一个 Kafka Producer 融合-kafka-go.v1/kafka

                  我的 docker 镜像已经构建成功,但是当我要使用 docker-compose-up 启动镜像时,会出现同样的问题:

                  xxxxx:~/cp-all-in-one/cp-all-in-one-community# docker-compose up
                  Recreating ms-c3alert ... done
                  Attaching to ms-c3alert
                  ms-c3alert | standard_init_linux.go:211: exec user process caused "no such file or directory"
                  ms-c3alert exited with code 1
                  

                  之后,测试线程和其他页面中的所有选项...我发现在 go build 语句中添加了 Fix -ldflags='-w -extldflags "-static"'

                  RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags='-w -extldflags "-static"' -a -installsuffix cgo -o c3alert .
                  

                  【讨论】:

                  • 我的解决方案也类似于上面答案中描述的解决方案以及@arulraj.net 提供的解决方案。必须ENV CGO_ENABLED=0 RUN go mod download RUN go build -a -installsuffix cgo -o myAppName . 然后它工作。
                  【解决方案11】:

                  我在使用 CGO 构建应用程序,然后将其复制到 scratch 图像时遇到了这个问题。那里不存在 Libc,所以我使用 alpine 作为我的基础镜像。

                  【讨论】:

                  • 谢谢。就是这样。
                  • 这个投票不多,但解决了我的问题。谢谢。
                  • 这是我的情况。谢谢!
                  【解决方案12】:

                  在 x86 机器上基于 ARM 构建 docker 映像时,我收到了相同的错误消息。问题通过安装QEMU并注册脚本解决

                  #Install the qemu     
                  sudo apt-get install qemu binfmt-support qemu-user-static packages
                  
                  #This step will execute the registering scripts
                  docker run --rm --privileged multiarch/qemu-user-static --reset -p yes 
                  

                  【讨论】:

                  • 它对我有用,没有注册步骤。
                  【解决方案13】:

                  在我的情况下,我必须将 run.sh 文件的行结尾从 CRLF 更改为 LF,并且错误消失了。

                  【讨论】:

                  • 我必须一遍又一遍地修复相同的文件。就像 Windows 想让我留在它的生态系统中一样。
                  • @JonathanCzitkovics 也许你应该检查你的 git 配置和代码编辑器的设置
                  【解决方案14】:

                  这里有多个正确答案。我没有看到它的 VIM 版本,所以在这里。在 VIM 中打开文件,检查底部状态行 for example,执行 set ff=dos(对于 CRLF)或 set ff=unix(对于 LF)。

                  【讨论】:

                    【解决方案15】:

                    这是因为shell脚本在windows中是格式化的,我们需要改成unix格式。 您可以在任何 Linux 系统上运行 dos2unix 命令。

                    dos2unix your-file.sh
                    

                    如果您无法访问 Linux 系统,您可以使用带有 dos2unix.exe 的 Git Bash for Windows

                    dos2unix.exe your-file.sh 
                    

                    【讨论】:

                    • 这里的最佳解决方案。 dos2unix 当然可以安装在 dockerfile 中,并在容器运行所需的任何/所有文件上运行 RUN 命令。如果在 Windows 机器上构建基于 linux 的图像,这是一个常见问题。即find ./src/ -iname "*.ts" | dos2unix 或任何适合个人情况的命令。
                    【解决方案16】:

                    我发现了一个特殊的边缘情况,我在 alpine 容器中使用了 tini init,但是由于我没有使用静态链接版本,并且默认安装了 Alpine uses musl libc rather than GNU LibC library,所以它会以相同的方式崩溃错误信息。

                    如果我理解这一点并花时间正确阅读文档,我会找到Tini Static,在更改为后解决了我的问题。

                    【讨论】:

                      【解决方案17】:

                      注意类似的错误,例如:

                      standard_init_linux.go:211: exec user process caused "no such file or directory"
                      

                      如果构建映像的架构与您的系统架构不匹配,则可能会发生这种情况。例如,尝试在x86_64 机器上运行为arm64 构建的映像会产生此错误。

                      【讨论】:

                      • 感谢您写这篇文章。这让我意识到我正在使用 ubuntu 构建并使用 alpine 运行,而 alpine 可能缺少一些需要的东西。
                      【解决方案18】:

                      假设您在 alpine 容器中运行 go 二进制文件时遇到了这个问题。在构建 bin 之前导出以下变量

                      # CGO has to be disabled for alpine
                      export CGO_ENABLED=0
                      

                      然后go build

                      【讨论】:

                      • 在 Dockerfile 中,在 go build 行之前添加 ENV CGO_ENABLED=0。这对我有用。
                      • 所以在Dockerfile中应该是:RUN export CGO_ENABLED=0 &amp;&amp; go build
                      • 拯救了我的一天。为我工作:-)
                      • 一个比禁用 CGo 更好的解决方案是安装 Go 二进制文件正在寻找的共享库。在 Alpine 中,这通常可以通过在 Dockerfile 中添加 RUN apk add --no-cache libc6-compat 来实现,以安装 glibc 兼容库。
                      • 谢谢,你拯救了我的一天。请注意,您可以使用以下链接:RUN CGO_ENABLED=0 go build
                      【解决方案19】:

                      我解决了这个问题,在 vscode 中设置我的设置。

                      1. 文件
                        1. 首选项
                          1. 设置
                            1. 文本编辑器
                              1. 文件
                              2. Eol - 设置为 \n

                      问候

                      【讨论】:

                        【解决方案20】:

                        如下更改入口点。它对我有用

                        ENTRYPOINT ["sh","/run.sh"]
                        

                        正如 tuomastik 指出的in the comments,the docs 要求第一个参数是可执行文件:

                        ENTRYPOINT 有两种形式:

                        ENTRYPOINT ["executable", "param1", "param2"](执行形式,首选)

                        ENTRYPOINT command param1 param2(外壳形式)

                        【讨论】:

                        • 为我工作。在这种情况下,我们甚至不需要在 shell 脚本中添加 #!/bin/sh。在 ENTRYPOINT 中提到“sh”就可以了
                        • 您能解释一下为什么以及何时需要“sh”吗?我看到很多例子都没有。
                        • @Opsse 没有"sh",正常的shell处理不会发生source
                        • 事实证明,在我的 ENTRYPOINT 脚本中,我使用 /bin/bash 作为 shell 解释器,但由于我的图像是基于 alpine 的,所以没有附带它。我将脚本bash 更改为sh 并解决了问题。
                        【解决方案21】:

                        “没有这样的文件或目录”来自Linux,我看到了以下原因:

                        第一个原因实际上是在您的容器中没有文件。有些人试图从主机运行命令而不将其添加到他们的图像中。有些人通过在他们想要运行的命令之上安装一个卷来隐藏他们的命令。如果您运行相同的容器,但使用 shell 而不是正常的入口点/cmd 值,并运行ls /path/to/cmd,您将看到它是否存在。

                        下一个原因是运行错误的命令。这通常出现在运行的命令的 json/exec 格式无法正确解析的情况下。如果您看到一个命令试图运行 ["app", 或类似的东西,则 Docker 没有解析 json 字符串,Linux 正在尝试使用 shell 将命令解析为字符串。如果您对 args 排序错误,例如试图运行-it 是一个标志,当它们必须放在图像名称之前时,你试图在图像名称之后放置标志。

                        对于 shell 脚本,如果带有 #! 的第一行指向容器内不存在的命令,则会出现此错误。对于某些人来说,这是试图在只有/bin/sh 的图像中运行bash。在您的情况下,这可以来自脚本中的 Windows 换行符。在您的编辑器中切换到 Linux/Unix 换行符将纠正该问题。

                        对于二进制文件,如果缺少链接库,则会出现此错误。当使用 libc 编译的 Go 命令,但使用 musl 在 alpine 上运行或根本没有任何库的从头开始时,我经常看到这种情况。您需要包含所有缺少的库或静态编译您的命令。要查看这些库链接,请在您的二进制文件中使用 ldd /your/app。

                        【讨论】:

                        • 谢谢!对于我的临时图像中的 go 应用程序,必须使用 CGO_ENABLED=0 重建
                        • 我的案例:1.可执行二进制文件是从alpine构建的,但是运行go命令的基础镜像是debian,所以出现错误。
                        • 在我的例子中,二进制文件是使用 GraalVM Native Builder 构建的,默认情况下它是以“动态”形式构建的,这显然需要一些 Alpine 中不存在的库。添加--static 构建静态二进制文件后,问题消失了。
                        【解决方案22】:

                        我在使用alpine 图像时遇到了同样的问题。

                        我的.sh 文件的第一行如下:

                        #!/bin/bash
                        

                        Alpine 没有 bash。所以将行改为

                        #!/bin/sh
                        

                        或使用 bash 安装

                        apk add --no-cache bash
                        

                        为我解决了这个问题。

                        【讨论】:

                        • 这个!在 Apline 的 Docker Hub 页面上应以粗体显示。
                        • 是的,就是这样。如果您使用带有Alpine docker 映像的entrypoint.sh 文件,请使用#!/bin/sh 而不是bash!
                        • 感谢上帝的回答!你救了我的脖子好先生。我扔硬币给你!
                        【解决方案23】:

                        这是一个 CRLF 问题。我用这个解决了这个问题:

                        git config --global core.eol lf
                        
                        git config --global core.autocrlf input
                        
                        find . -type f -print0 | xargs -0 dos2unix
                        

                        【讨论】:

                          【解决方案24】:

                          将此添加到您的 Dockerfile 中

                          RUN cat /run.sh | tr -d '\r' > /run.sh
                          

                          【讨论】:

                            【解决方案25】:

                            使用 Notepad++ 将 CRLF 替换为 LF

                            1. Notepad++ 的查找/替换功能可以很好地处理这个需求 很好。只需调出替换对话框 (CTRL+H),选择 扩展搜索模式(ALT+X),搜索“\r\n”并替换为 “\n”:
                            2. 点击全部替换 (ALT+A)

                            重建并运行 docker 镜像应该可以解决您的问题。

                            【讨论】:

                              猜你喜欢
                              • 2019-09-19
                              • 2021-10-23
                              • 2019-03-09
                              • 2021-05-16
                              • 1970-01-01
                              • 2018-12-07
                              • 2020-10-25
                              • 2020-08-03
                              • 2018-10-31
                              相关资源
                              最近更新 更多