Unable to start Docker image with Rust executable

I am trying to create an image with my binary (written in Rust), but I am getting different errors. This is my Dockerfile :

 FROM scratch COPY binary / COPY .env / COPY cert.pem /etc/ssl/ ENV RUST_BACKTRACE 1 CMD /binary 

The building finishes fine, but when I try to start it, I get the following:

 $ 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 

And this:

 $ docker run binary /binary standard_init_linux.go:195: exec user process caused "no such file or directory" 

I have no idea what to do. The error message looks very strange to me. According to the official documentation of Docker Docker version 18.02.0-ce, build fc4de447b5

I tested the C ++ program and it works great with both clang and gcc.

It does not work with scratch , alpine , busybox or bash images, but it works with postgresql , ubuntu and debian images. The exact problem is something related to rust and lightweight docker images - everything works fine otherwise.

+7
docker dockerfile rust
source share
1 answer

As @ Oleg Sklar noted, the problem is that the Rust binary is dynamically linked.

This can be a bit confusing because many people who heard about Rust also heard that Rust binaries are statically linked, but this refers to the rust code in the boxes: the boxes are linked statically because they are all known at the moment of compilation. This does not apply to existing C dynamic libraries to which the program can be bound, for example, to libc and other required libraries. Often these libraries can also be created as statically linked artifacts (see the end of this post). To check if your program or library is dynamically linked, you can use the ldd utility:

 $ 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) 

You need these libraries in your Docker image. You will also need a translator; To get its path, you can use the objdump utility:

 $ 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. 

Copy the files to the expected directories, and everything will be fine.

There is also a second option, which is to use a rust-musl-builder image. There are some problems with postgresql and diesel , but for most projects this would be nice. It works by creating a statically linked executable that you can simply copy and use. This option is much more preferable than using the interpreter and dynamic libraries if you want to provide a docker image with a smaller size and without all these useless additional data, such as an interpreter, unused libraries, etc.

+7
source share

All Articles