Docker run出错standard_init_linux.go:211处理
出错场景
最近在学习Rust基础知识,工作中也有在使用Docker部署环境,在学习过程中想把Rust编写的Hello World部署到Docker中运行。参考了Docker的官网,制作了Docker镜像,并执行Docker run之后,提示错误,standard_init_linux.go:211: exec user process caused “no such file or directory”,搜索无果,后对比官方示例,终于解决掉了,特此记录下来,备忘。
$ docker run hello_rust
standard_init_linux.go:211: exec user process caused "no such file or directory"
$
详细步骤
1.创建hello_rust项目并编译
按照如下步骤创建并编译hello_rust项目,在target下找到hello_rust可执行文件,具体rust相关的工具可参考rust官网的文档,具体的编码内容从略。
执行./hello_rust后可打印出Hello, world!
$ cd rust-demo
$ $ cargo new hello_rust
Created binary (application) `hello_rust` package
$ cd hello_rust
$ cargo build --release
Compiling hello_rust v0.1.0 (/home/zxl/rust-demo/hello_rust)
Finished release [optimized] target(s) in 11.16s
$ cd target/release/
$ ls
build deps examples hello_rust hello_rust.d incremental
$ ./hello_rust
Hello, world!
$
2.Docker部署hello_rust
2.1 创建镜像
此处未按照网上常用用的方式创建一个基于Ubuntu或者其他的镜像,而是基于Docker官网的scratch(空镜像)创建。
Ps:也是想看下Docker和虚拟机的区别
2.1.1 准备工作
1.新建docker-demo目录;
2.将hello_rust可执行文件拷贝到docker-demo目录;
$ mkdir docker-demo
$ ls
Dockerfile hello_rust
2.1.2 编写Dockerfile
Docker官网有相应的例子。基础镜像创建
1.使用scratch作为父镜像
2.将hello_rust拷贝到/目录
3.容器启动后执行/hello_rust命令
$ cat Dockerfile
FROM scratch
COPY hello_rust /
CMD ["/hello_rust"]
2.1.3.build镜像
示例中的hello_world镜像为从Docker Hub上下载的官方例子。
$ docker build -t hello_rust .
Sending build context to Docker daemon 2.86MB
Step 1/3 : FROM scratch
--->
Step 2/3 : COPY hello_rust /
---> faf61cf1b2e6
Step 3/3 : CMD ["/hello_rust"]
---> Running in 0dd3e4b74cea
Removing intermediate container 0dd3e4b74cea
---> dd542a1ce6ee
Successfully built dd542a1ce6ee
Successfully tagged hello_rust:latest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello_rust latest dd542a1ce6ee 5 minutes ago 2.86MB
hello-world latest bf756fb1ae65 9 months ago 13.3kB
2.2 运行镜像
2.2.1 运行自定义镜像[hello_rust]
自定义镜像报错。
$ docker run hello_rust
standard_init_linux.go:211: exec user process caused "no such file or directory"
$
2.2.2 运行官方镜像[hello_world]
官方镜像正常运行。
$ docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
$
问题分析
刚开始并未理解"no such file or directory"指的是什么文件,因COPY指令已将hello_rust可执行文件拷贝到镜像中,于是猜测是否hello_rust依赖的文件未在镜像中,于是使用ldd命令进行测试,结果如下
1.hello_rust:cargo build创建的可执行文件,依赖了共享库文件
2.hello:docker hello_world镜像中的可执行文件(静态编译),参考:https://github.com/docker-library/hello-world/
$ ldd hello_rust
linux-vdso.so.1 => (0x00007ffec8da2000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fadefa1a000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fadef812000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fadef5f5000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fadef3df000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fadef015000)
/lib64/ld-linux-x86-64.so.2 (0x00007fadefe5b000
$ ldd hello
不是动态可执行文件
由上述分析可以推断,缺少的文件,为hello_rust依赖的共享库文件。下面开始验证猜测。使用静态编译方式,重新编译hello_rust项目,步骤如下
1.安装rust的交叉编译选项
2.使用交叉编译,对hello_rust进行静态编译
$ rustup target add x86_64-unknown-linux-musl
$ cd hello_rust
$ cargo build --release --target=x86_64-unknown-linux-musl
$ cd target/x86_64-unknown-linux-musl/release
$ ls
build deps examples hello_rust hello_rust.d incremental
按照第2章[2.Docker部署hello_rust]的步骤重写执行后正常,问题解决
$ docker run hello_rust
Hello, world!
$
总结
根据上面的总结可知,Docker的镜像制作是需要将相关的依赖内容全部包含,从scratch开始构建是一项复杂的工作,需要添加所有的依赖,工作中一般使用Docker Hub中已存在的镜像进行二次封装(可能会比较大)。当二次封装也出现本文描述的情况时,可以考虑是否缺失依赖项,并可以尝试按照本文的方向进行处理。仅仅时方向,具体问题需再具体分析。