/Lib64/Ld-Linux-X86-64.So.2: No Such File or Directory Error

Could not open '/lib64/ld-linux-x86-64.so.2' on CentOS8 container

Hope you are enjoying you containers journey,

About your error message, you can check this: qemu-x86_64: Could not open '/lib64/ld-linux-x86-64.so.2': No such file or directory

But I also have some suggestions, that could help you:
Since i dont have your dockerfile, i tried with this one:

FROM centos:8

RUN yum -y update && yum -y install wget
RUN wget https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz
RUN sudo tar -C /usr/local -xf go1.13.4.linux-amd64.tar.gz
RUN echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bash_profile
RUN source ~/.bash_profile

lets build it:

❯ docker build -t so-go-version-centos8 .

The problem is that with the centos8 docker images, i couldn't update or install anything:
(https://serverfault.com/questions/1091791/the-latest-centos8-docker-image-cannot-run-yum)

❯ docker run -it centos:8
[root@d7c652e4ac65 /]# yum install wget
Failed to set locale, defaulting to C.UTF-8
CentOS Linux 8 - AppStream 0.0 B/s | 0 B 00:00
Errors during downloading metadata for repository 'appstream':
- Curl error (6): Couldn't resolve host name for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container [Could not resolve host: mirrorlist.centos.org]
Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: Curl error (6): Couldn't resolve host name for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container [Could not resolve host: mirrorlist.centos.org]

[root@d7c652e4ac65 /]# yum install golang
Failed to set locale, defaulting to C.UTF-8
CentOS Linux 8 - AppStream 95 B/s | 38 B 00:00
Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist

[root@d7c652e4ac65 /]# yum update
Failed to set locale, defaulting to C.UTF-8
CentOS Linux 8 - AppStream

So I decided to avoid the system update and the installation of wget and use the dockerfile ADD command (the difference between ADD and COPY is that we can directly, with ADD, copy things from URLs instead of only our host filesystem) and adding go path to $PATH env variable with dockerfile ENV command, here is how my df looks like:

FROM centos:8

ADD https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz .
RUN tar -C /usr/local -xf go1.13.4.linux-amd64.tar.gz
ENV PATH=$PATH:/usr/local/go/bin

lets build it:

❯ docker build --no-cache -t so-go-version-centos8 -f dockerfile-centos8 .
[+] Building 14.2s (8/8) FINISHED
=> [internal] load build definition from dockerfile-centos8 0.0s
=> => transferring dockerfile: 218B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:8 1.0s
=> CACHED https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz 0.0s
=> CACHED [1/3] FROM docker.io/library/centos:8@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177 0.0s
=> [2/3] ADD https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz . 2.2s
=> [3/3] RUN tar -C /usr/local -xf go1.13.4.linux-amd64.tar.gz 7.5s
=> exporting to image 3.2s
=> => exporting layers 3.2s
=> => writing image sha256:26a8caea62889668498ca1d513b7db2c95b084a1d0020512e0c16dee365a880c 0.0s
=> => naming to docker.io/library/so-go-version-centos8 0.0s
   /mnt/c/U/b/De/w/p/kind/manifests/stackoverflow/centos8-container-go-version ─────────────────────── 15s   02:21:46 _x0017_
❯ docker run -it so-go-version-centos8
[root@78947ab8771a /]# go version
go version go1.13.4 linux/amd64
[root@78947ab8771a /]#

it worked well.

Centos8 docker image is then limited since i cant install what i need, So you can replace it by centos:7 docker image instead.

solution 2: try yum install golang
as @Para suggested, you could also directly install golang with yum, but "yum install -y golang" will not work. SO we have to install it manually, as we have done.

solution3: You can directly use an official golang docker image, i.e:

❯ docker run -it golang:buster
root@ed9f31e4a45a:/go# go version
go version go1.18.1 linux/amd64
root@ed9f31e4a45a:/go#

Hope this has helped you, bguess.

No such file or directory on any executable file in docker

The program binary itself is (in most cases) not self-sufficient; instead, it depends on a number of dynamic libraries (usually at least a C standard library) and a dynamic linker (also known as the interpreter), which knows how to load the binary into the memory and to link it with these libraries.

The information about what linker the system has to use to launch the specific program and which libraries the program requires is stored inside the program binary itself. You may easily extract this information using tools like ldd and readelf. For example, this is how you may find all the stuff /bin/ls needs to run successfully:

$ ldd /bin/ls
linux-vdso.so.1 (0x00007ffec7b46000)
libcap.so.2 => /usr/lib/libcap.so.2 (0x00007f805384c000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f8053642000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f80538ae000)

Or, more verbosely:

$ readelf -a /bin/ls
...
Program Headers:
Type Offset VirtAddr PhysAddr
...
INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
...
Dynamic section at offset 0x22a58 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libcap.so.2]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]

Note: my examples are taken from Arch box, so your results may be different, yet close to this. The main point here is that the binary relies on ld-linux, which is true for both Arch and Ubuntu (see below).

When you ask the kernel to execute ls, it reads the program binary, looks for the linker the program requires (/lib64/ld-linux-x86-64.so.2) in the filesystem and runs it. The linker then loads ls and all its dependencies into the memory; only after this the code of ls itself is executed.

The problem is that different Linux distributions (and different versions of them) have different environments. While it is common for distros to use GNU libc (glibc) as the C standard library and its ld-linux as the linker, there also are distros using other libc variants and other linkers. Alpine is one of such distros: it uses musl libc and its own linker ld-musl:

$ docker run -it alpine
/ # ldd /bin/ls
/lib/ld-musl-x86_64.so.1 (0x7f40c772d000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f40c772d000)

This means that Alpine does not have /lib64/ld-linux-x86-64.so.2 file (by default; see Running glibc programs). That is why running ls built for glibc-based system (Ubuntu in your case) inside an Alpine container fails: the kernel reads the binary, learns that it needs /lib64/ld-linux-x86-64.so.2 to load this program, and finds no such file inside the filesystem.

When the kernel is unable to find the interpreter requested by the program, it returns the same error as when you ask it to execute the non-existent file:

man 2 execve
...
ENOENT The file pathname or a script or ELF interpreter does not exist.

This is why you get no such file or directory, which is somewhat misleading, as it does not say which file is not found — the linker, not the program itself.

Given that ls does not have lots of dependencies, chances are good that the trick you try to do will work with containers having glibc-based systems inside:

$ docker run -it -v /bin/ls:/test/ls alpine /test/ls
exec /test/ls: no such file or directory

...

$ docker run -it -v /bin/ls:/test/ls ubuntu /test/ls
bin dev home lib32 libx32 mnt proc run srv test usr
boot etc lib lib64 media opt root sbin sys tmp var

...

$ docker run -it -v /bin/ls:/test/ls archlinux /test/ls
bin dev home lib64 opt root sbin sys tmp var
boot etc lib mnt proc run srv test usr

However, running host binaries inside the container is not what you are supposed to do and there is no guarantee that things won't go haywire, so make sure you really know what you do when employing such tricks.

Linux check dependencies of executable

Oooooooookay, that's not strictly an answer to the initial question, aka on how to figure out which specific library I'm missing, however I fixed my specific issue.

sudo apt install alien
wget https://distrib-coffee.ipsl.jussieu.fr/pub/linux/altlinux/p10/branch/x86_64/RPMS.classic/lsb-core-5.0-alt1.x86_64.rpm
sudo alien --to-deb -c lsb-core-5.0-alt1.x86_64.rpm

And then providing this *.deb file to the Docker container and installing it fixed the issue. So I guess it was just lsb-core missing, and obtaining the .rpm version of it and converting it to the .deb format is compatible enough for my usecase!

I stumbled upon this solution thanks to this wonderful thread.



Related Topics



Leave a reply



Submit