【问题标题】:Adding Linux utilities to docker image based on busybox基于busybox的docker镜像添加Linux实用程序
【发布时间】:2019-01-09 05:39:15
【问题描述】:

当我为 busybox 容器尝试 df -h 时,我得到以下结果:

$ docker run -it busybox du -h  
# expected results

我需要的是df -b 的输出,它给了我以下信息:

$ docker run -it busybox du -b                                                                     
du: invalid option -- b
BusyBox v1.30.0 (2018-12-31 18:16:17 UTC) multi-call binary.

Usage: du [-aHLdclsxhmk] [FILE]...

Summarize disk space used for each FILE and/or directory

    -a  Show file sizes too
    -L  Follow all symlinks
    -H  Follow symlinks on command line
    -d N    Limit output to directories (and files with -a) of depth < N
    -c  Show grand total
    -l  Count sizes many times if hard linked
    -s  Display only a total for each argument
    -x  Skip directories on different filesystems
    -h  Sizes in human readable format (e.g., 1K 243M 2G)
    -m  Sizes in megabytes
    -k  Sizes in kilobytes (default)

由于许多标准实用程序在busybox 图像中被修剪或不存在,因此这种行为并不奇怪。作为dockerhub的busybox页面suggests

FROM busybox
COPY ./my-static-binary /my-static-binary
CMD ["/my-static-binary"]

所以,我创建了一个包含以下内容的 Dockerfile,试图将我的 Ubuntu 16.04 du 二进制文件复制到映像中:

FROM busybox
COPY /usr/bin/du /bin/du
CMD ["/bin/du", "-b"]

但是当我尝试docker build 时,我收到以下错误:

$ docker build .              
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> 3a093384ac30
Step 2/3 : COPY /usr/bin/du /bin/du
COPY failed: stat /var/lib/docker/tmp/docker-builder362173879/usr/bin/du: no such file or directory

我不知道将实用程序添加到此类最小图像是否是正确的方法,但如果您让我知道实用程序(例如(完整)ducurl 等)可以使用的方式,我将不胜感激鉴于没有像 apt 这样的包管理器,所以添加。

【问题讨论】:

    标签: docker dockerfile busybox


    【解决方案1】:

    如果只是 Busybox Docker 基础映像不能满足您的需求,您可以将 Dockerfile 更改为基于功能更全的 Linux 发行版。 FROM ubuntu 非常常见,包括 GNU 版本的 Unix 工具集(及其各种供应商扩展); FROM alpine 也很常见,它基于 Busybox 和一个最小的包管理器。

    另一个好的答案是将自己限制在POSIX.1:du(1) is not required to support a -b option 中定义的功能。如果您尝试编写基于 Alpine 的映像或在非 Linux 系统(MacOS 是当今最突出的示例)上运行,这将有所帮助。

    您可能无法成功地将单个二进制文件从主机系统复制到 Docker 映像中,路径问题除外,因为库环境可能非常不同。如果您在主机上运行ldd $(which du),则其中列出的所有库都需要存在于映像中并且具有相似的版本。 busybox 基本映像可能甚至不包含 libc.so.6,这是大多数动态链接二进制文件的最低要求。

    您的问题的正确答案是编写一个多阶段 Dockerfile,该文件的第一阶段带有完整的 C 工具链,用于构建GNU Coreutils 的静态版本,然后是复制它的第二阶段。对于一个可能不是您真正想要运行的核心应用程序的一部分的工具来说,这需要做很多工作。

    【讨论】:

    • 非常感谢大卫。我非常感谢您的详细回答。我的问题很简单。主要问题是在基于派生图像的容器中使用du -b,其父图像是busybox的某种风格。为了解决这个问题,我将使用du -k 并通过乘法将其转换为字节。我很好奇如何解决这个问题,你的回答真的很有启发性。
    • 还可以考虑使用语言原生工具(例如,Python 的os.walk),或者,如果您的应用程序确实是一个面向 shell 脚本的应用程序来执行某种文件系统管理,只需在主机上运行(并避免文件系统映射和权限问题)。
    【解决方案2】:

    COPY 因以下限制而无法工作:

    COPY 遵循以下规则:

    路径必须在构建的上下文中;你不能复制 ../something /something,因为 docker build 的第一步 是将上下文目录(和子目录)发送到docker 守护进程。

    您可以在Dockerfile documentation阅读更多内容。

    为了使您的busybox图像正常工作,您应该执行以下操作:

    1. du复制到Dockerfile所在的目录:cp /usr/bin/du .
    2. 更新您的Dockerfile:
    FROM busybox
    COPY du /du
    CMD ["du", "-b"]
    
    3. 重建你的镜像:`docker build .`

    根据busybox docker documentation,您应该将复制的二进制文件直接放到/,而不是/bin/

    【讨论】:

    • 谢谢。它解决了这个问题,但是在运行容器时我得到了standard_init_linux.go:195: exec user process caused "no such file or directory"。现在可能是依赖问题?
    • 尝试运行以下命令:docker build -t mybusybox:1.0 . 然后docker run -it --rm mybusybox:1.0 是否会出现同样的错误?
    • 我尝试将其复制到/bin/du 以将其替换为原始du 无济于事。即使使用您指定的COPY du /du,当我使用docker run -it mybusybox:2 sh 检查容器并尝试./du 尽管我可以在ls 的结果中看到它时,我得到sh: ./du: not found
    • 所以你将du复制到/(不是/bin/du),在容器ls /中显示du但如果你执行du(不是@987654347 @) 文件没找到对吧?
    • 当我在将du 复制到其根目录(/)的容器中执行du 时,它使用/bin/du 中没有-b 的默认du .当我将du 复制到/bin/du(替换图像的原始du)时,会导致我在第一条评论中提到的错误。如果我运行 ./du 以防它被复制到 / 并尝试在我的当前目录为 / 时运行它,则会发生未找到错误。
    猜你喜欢
    • 1970-01-01
    • 2017-10-27
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 2019-08-03
    • 2019-12-21
    • 1970-01-01
    相关资源
    最近更新 更多