作者:GZJYGZJYGZJY | 来源:互联网 | 2022-12-25 17:36
我试图用我的二进制文件(用Rust编写)创建一个图像,但我得到了不同的错误.这是我的Dockerfile
:
FROM scratch
COPY binary /
COPY .env /
COPY cert.pem /etc/ssl/
ENV RUST_BACKTRACE 1
CMD /binary
建筑完成很好但是当我尝试运行它时我得到了这个:
$ docker run binary
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown.
ERRO[0000] error waiting for container: context canceled
还有这个:
$ docker run binary /binary
standard_init_linux.go:195: exec user process caused "no such file or directory"
我不知道该怎么做.错误消息对我来说很奇怪.根据官方Docker文档,它必须工作.
系统信息:最新的Arch Linux和Docker:
Docker version 18.02.0-ce, build fc4de447b5
我用C++程序测试过,它的工作正常,包括clang和gcc.
它不工作scratch
,alpine
,busybox
,或 bash
基于图像,但它一起工作postgresql
,ubuntu
和debian
图像.确切的问题是与Rust和轻量级docker图像有关的东西 - 否则一切正常.
1> Victor Polev..:
正如@Oleg Sklyar指出的那样,问题是Rust二进制文件是动态链接的.
这可能有点令人困惑,因为许多听说过Rust的人也听说过Rust二进制文件是静态链接的,但这是指条件箱中的Rust代码:crate是静态链接的,因为它们在编译时都是已知的.这并不是指程序可能链接到的现有C动态库,例如libc和其他必备库.通常,这些库也可以构建为静态链接的工件(请参阅本文末尾).要检查您的程序或库是否是动态链接的,您可以使用ldd
实用程序:
$ ldd target/release/t
linux-vdso.so.1 (0x00007ffe43797000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fa78482d000)
librt.so.1 => /usr/lib/librt.so.1 (0x00007fa784625000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fa784407000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fa7841f0000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fa783e39000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fa784ca2000)
您需要在Docker镜像中使用这些库.你还需要翻译; 获取它的路径你可以使用objdump
实用程序:
$ LANG=en objdump -s -j .interp target/release/t
target/release/t: file format elf64-x86-64
Contents of section .interp:
0270 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux-
0280 7838362d 36342e73 6f2e3200 x86-64.so.2.
将文件复制到预期的目录中,一切正常.
还有第二个选项是使用rust-musl-builder
泊坞窗图像.有一些问题postgresql
和diesel
但对于大多数的项目也将是一件好事.它的工作原理是生成一个静态链接的可执行文件,您可以复制和使用它.如果要提供较小的docker镜像并且没有所有无用的额外数据(如解释器,未使用的库等),则此选项比使用解释器和动态库更受欢迎.
我不会*只是将库(特别是*不是*解释器)从编译系统复制到Docker镜像.您应该使用分发包管理器在Docker映像中安装库,然后在容器内构建Rust程序,自动链接到相应的库.您还可以选择使用MUSL构建静态二进制文件.
像那样?https://docs.docker.com/develop/develop-images/multistage-build/#before-multi-stage-builds如果是这样,会有什么区别?翻译有什么特别之处?
是的,多级构建是适合的工具; 你不想在最终图像中运送Rust编译器.我从来没有听说过有人在机器之间复制解释器,所以感觉超级可疑.Rust playground是一个静态二进制文件,所以你可以使用静态链接,但是你在某些方面它变得正确复杂.有像[rust-musl-builder](https://github.com/emk/rust-musl-builder)这样的图像可以让它更容易.