docker - docker中的任何可执行文件上都没有这样的文件或目录

标签 docker ubuntu executable file-not-found

我尝试从/bin 运行 ls 的副本(并尝试在容器中不在/bin 中的任何可执行文件上)并得到错误。

docker run -v ~/Desktop/test:/test alpine:latest /test/ls
exec /test/ls: no such file or directory
当我运行另一个命令时,我可以看到该文件。
docker run -v ~/Desktop/test:/test alpine:latest ls /test
ls
我尝试设置 chmode +x 在此文件上,但不进行任何更改。改变形象也没有任何影响。我已经更新了 docker 并且全部由 apt-get update && apt-get upgrade 打包.
我使用 Ubuntu 20.04.3 LTS。
Docker 版本 20.10.17,构建 100c701
检查
{
    "Id": "abd66c400e6f58313d71c63c92688472874cdd4393d42e22df23a90264083b33",
    "Created": "2022-06-13T19:59:49.630474765Z",
    "Path": "/test/ls",
    "Args": [],
    "State": {
        "Status": "exited",
        "Running": false,
        "Paused": false,
        "Restarting": false,
        "OOMKilled": false,
        "Dead": false,
        "Pid": 0,
        "ExitCode": 1,
        "Error": "",
        "StartedAt": "2022-06-13T19:59:50.017551978Z",
        "FinishedAt": "2022-06-13T19:59:50.016401363Z"
    },
    "Image": "sha256:0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b",
    "ResolvConfPath": "/var/lib/docker/containers/abd66c400e6f58313d71c63c92688472874cdd4393d42e22df23a90264083b33/resolv.conf",
    "HostnamePath": "/var/lib/docker/containers/abd66c400e6f58313d71c63c92688472874cdd4393d42e22df23a90264083b33/hostname",
    "HostsPath": "/var/lib/docker/containers/abd66c400e6f58313d71c63c92688472874cdd4393d42e22df23a90264083b33/hosts",
    "LogPath": "/var/lib/docker/containers/abd66c400e6f58313d71c63c92688472874cdd4393d42e22df23a90264083b33/abd66c400e6f58313d71c63c92688472874cdd4393d42e22df23a90264083b33-json.log",
    "Name": "/cranky_pare",
    "RestartCount": 0,
    "Driver": "overlay2",
    "Platform": "linux",
    "MountLabel": "",
    "ProcessLabel": "",
    "AppArmorProfile": "docker-default",
    "ExecIDs": null,
    "HostConfig": {
        "Binds": [
            "/home/egor/Desktop/test:/test"
        ],
        "ContainerIDFile": "",
        "LogConfig": {
            "Type": "json-file",
            "Config": {}
        },
        "NetworkMode": "default",
        "PortBindings": {},
        "RestartPolicy": {
            "Name": "no",
            "MaximumRetryCount": 0
        },
        "AutoRemove": false,
        "VolumeDriver": "",
        "VolumesFrom": null,
        "CapAdd": null,
        "CapDrop": null,
        "CgroupnsMode": "host",
        "Dns": [],
        "DnsOptions": [],
        "DnsSearch": [],
        "ExtraHosts": null,
        "GroupAdd": null,
        "IpcMode": "private",
        "Cgroup": "",
        "Links": null,
        "OomScoreAdj": 0,
        "PidMode": "",
        "Privileged": false,
        "PublishAllPorts": false,
        "ReadonlyRootfs": false,
        "SecurityOpt": null,
        "UTSMode": "",
        "UsernsMode": "",
        "ShmSize": 67108864,
        "Runtime": "runc",
        "ConsoleSize": [
            0,
            0
        ],
        "Isolation": "",
        "CpuShares": 0,
        "Memory": 0,
        "NanoCpus": 0,
        "CgroupParent": "",
        "BlkioWeight": 0,
        "BlkioWeightDevice": [],
        "BlkioDeviceReadBps": null,
        "BlkioDeviceWriteBps": null,
        "BlkioDeviceReadIOps": null,
        "BlkioDeviceWriteIOps": null,
        "CpuPeriod": 0,
        "CpuQuota": 0,
        "CpuRealtimePeriod": 0,
        "CpuRealtimeRuntime": 0,
        "CpusetCpus": "",
        "CpusetMems": "",
        "Devices": [],
        "DeviceCgroupRules": null,
        "DeviceRequests": null,
        "KernelMemory": 0,
        "KernelMemoryTCP": 0,
        "MemoryReservation": 0,
        "MemorySwap": 0,
        "MemorySwappiness": null,
        "OomKillDisable": false,
        "PidsLimit": null,
        "Ulimits": null,
        "CpuCount": 0,
        "CpuPercent": 0,
        "IOMaximumIOps": 0,
        "IOMaximumBandwidth": 0,
        "MaskedPaths": [
            "/proc/asound",
            "/proc/acpi",
            "/proc/kcore",
            "/proc/keys",
            "/proc/latency_stats",
            "/proc/timer_list",
            "/proc/timer_stats",
            "/proc/sched_debug",
            "/proc/scsi",
            "/sys/firmware"
        ],
        "ReadonlyPaths": [
            "/proc/bus",
            "/proc/fs",
            "/proc/irq",
            "/proc/sys",
            "/proc/sysrq-trigger"
        ]
    },
    "GraphDriver": {
        "Data": {
            "LowerDir": "/var/lib/docker/overlay2/115140c86b11eb773f30d2329ec05388224e75dfbcef9977c87bb3f0e32e8769-init/diff:/var/lib/docker/overlay2/22348355d634b9183f798e9622f71809a9a62a7c6accdf723aa72d979e3ba7f4/diff",
            "MergedDir": "/var/lib/docker/overlay2/115140c86b11eb773f30d2329ec05388224e75dfbcef9977c87bb3f0e32e8769/merged",
            "UpperDir": "/var/lib/docker/overlay2/115140c86b11eb773f30d2329ec05388224e75dfbcef9977c87bb3f0e32e8769/diff",
            "WorkDir": "/var/lib/docker/overlay2/115140c86b11eb773f30d2329ec05388224e75dfbcef9977c87bb3f0e32e8769/work"
        },
        "Name": "overlay2"
    },
    "Mounts": [
        {
            "Type": "bind",
            "Source": "/home/egor/Desktop/test",
            "Destination": "/test",
            "Mode": "",
            "RW": true,
            "Propagation": "rprivate"
        }
    ],
    "Config": {
        "Hostname": "abd66c400e6f",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": true,
        "AttachStderr": true,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "Cmd": [
            "/test/ls"
        ],
        "Image": "alpine:latest",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": null,
        "Labels": {}
    },
    "NetworkSettings": {
        "Bridge": "",
        "SandboxID": "fb64f195f203033f02b9c5555e0b1d2cdd2819f3ac12f3046416f8e13378bc3d",
        "HairpinMode": false,
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "Ports": {},
        "SandboxKey": "/var/run/docker/netns/fb64f195f203",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "EndpointID": "",
        "Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "MacAddress": "",
        "Networks": {
            "bridge": {
                "IPAMConfig": null,
                "Links": null,
                "Aliases": null,
                "NetworkID": "cb261cd6eca2ddb567984e2d7d9e6df14008c774d73f0d76129da6c8edc6955c",
                "EndpointID": "",
                "Gateway": "",
                "IPAddress": "",
                "IPPrefixLen": 0,
                "IPv6Gateway": "",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "MacAddress": "",
                "DriverOpts": null
            }
        }
    },
    "CreatedTime": 1655150389630
}

最佳答案

程序二进制本身(在大多数情况下)不是自给自足的;相反,它依赖于许多动态库(通常至少是一个 C 标准库)和一个动态链接器(也称为解释器),它知道如何将二进制文件加载到内存中并将其与这些库链接。
有关系统必须使用什么链接器来启动特定程序以及程序需要哪些库的信息存储在程序二进制文件本身中。您可以使用 ldd 等工具轻松提取此信息。和 readelf .例如,您可以通过以下方式找到所有内容 /bin/ls需要成功运行:

$ 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)
或者,更详细地说:
$ 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]
备注 : 我的例子取自 Arch box,所以你的结果可能不同,但接近这个。这里的要点是二进制依赖于ld-linux。 ,这对于 Arch 和 Ubuntu 都是如此(见下文)。
当你要求内核执行 ls ,它读取程序二进制文件,在文件系统中查找程序所需的链接器(/lib64/ld-linux-x86-64.so.2)并运行它。然后链接器加载 ls并将其所有依赖项放入内存;只有在此之后 ls 的代码本身被执行。
问题是不同的 Linux 发行版(以及它们的不同版本)有不同的环境。虽然发行版通常使用 GNU libc (glibc) 作为 C 标准库及其 ld-linux作为链接器,也有使用其他 libc 变体和其他链接器的发行版。 Alpine 就是这样的发行版之一:它使用 musl libc 和它自己的链接器 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)
这意味着 Alpine 没有 /lib64/ld-linux-x86-64.so.2文件(默认情况下;见 Running glibc programs)。这就是为什么运行 ls专为 glibc 打造基于 Alpine 容器内的基于系统(在您的情况下为 Ubuntu)失败:内核读取二进制文件,获悉它需要 /lib64/ld-linux-x86-64.so.2加载这个程序,并在文件系统中找不到这样的文件。
当内核无法找到程序请求的解释器时,它会返回与您要求它执行不存在的文件时相同的错误:
man 2 execve
...
ENOENT The file pathname or a script or ELF interpreter does not exist.
这就是为什么你会得到 no such file or directory ,这有点误导,因为它没有说明找不到哪个文件——链接器,而不是程序本身。
鉴于 ls没有很多依赖项,您尝试使用的技巧很可能适用于具有 glibc 的容器内部基于系统:
$ 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
然而,在容器内运行主机二进制文件并不是你应该做的,也不能保证事情不会发生困惑,所以在使用这些技巧时要确保你真的知道你在做什么。

关于docker - docker中的任何可执行文件上都没有这样的文件或目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72608596/

相关文章:

angular - Headless Chrome 完成执行 Karma 单元测试时,Docker 任务失败

c - 将 go linker 构建为独立工具

windows - EXE、DLL、SYS等文件类型是如何一起调用的?

docker - 与 Rancher 的跨容器/主机通信

linux - docker - 拉取图像并获取它的 id (linux cli)

docker - 是否需要使用 Azure 容器注册表才能使用 Azure 容器?

ubuntu - FireHol 溢出日志

linux - WPS office (alpha) 安装后损坏的 libc.so.6

kotlin - 在桌面上使用 Compose 的启动程序在 Linux 上非常滞后

windows - Windows 程序的自定义安装文件