【问题标题】:What does running the multiarch/qemu-user-static does before building a container?在构建容器之前运行 multiarch/qemu-user-static 有什么作用?
【发布时间】:2022-07-07 05:48:45
【问题描述】:

谁能简单的解释一下是什么

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -c yes

在从 Dockerfile 执行 docker build 容器之前调用时执行?

我的想法是允许将其他架构中的容器使用到 X86 架构中,但我不确定我是否完全理解我在某些网站上找到的解释。

上述指令(docker run)的存在是否意味着构建阶段的Dockerfile是针对另一个架构的?

【问题讨论】:

    标签: docker qemu


    【解决方案1】:

    我最近也有这个问题,我没有完整的答案,但这是我所知道的,或者至少是相信的:

    设置和测试

    设置的魔力 - 每次重新启动系统都需要一次,就是这样:

    # start root's docker (not via any `-rootless` scripts, obviously)
    sudo systemctl start docker
    # setup QEMU static executables formats
    sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
    # test
    docker run --rm -t arm64v8/ubuntu uname -m
    # shoudl expect:
    # >> aarch64
    # optional: shutdown root's docker
    sudo systemctl stop docker
    

    请注意,测试示例假设您正在运行您自己的“rootless-”docker,因此是作为您自己,而不是作为 root(也不是通过 sudo)运行,而且它运行得很好。

    血腥细节

    ...如果您想了解这是如何/为什么起作用的,这很重要。

    此信息的主要来源:

    完成这项工作的基本技巧是将新的“魔术”字符串安装到内核进程空间中,以便当 (ARM) 可执行文件在 docker 映像中运行时,它可以识别 bin-fmt 并使用 QEMU 解释器(从multiarch/* docker 镜像)来执行它。在我们设置 bin 格式之前,内容如下所示:

    root@odysseus # mount | grep binfmt_misc
    systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=35,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=45170)
    binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
    root@odysseus # ls /proc/sys/fs/binfmt_misc/
    jar  llvm-6.0-runtime.binfmt  python2.7  python3.6  python3.7  python3.8  register  sbcl  status
    

    在我们启动(root 的)dockerd 并设置格式之后:

    root@odysseus # systemctl start docker
    root@odysseus # docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
    Setting /usr/bin/qemu-alpha-static as binfmt interpreter for alpha
    Setting /usr/bin/qemu-arm-static as binfmt interpreter for arm
    [...]
    root@odysseus # ls /proc/sys/fs/binfmt_misc/
    jar                      python3.8        qemu-armeb       qemu-microblazeel  qemu-mipsn32    qemu-ppc64le  qemu-sh4eb        qemu-xtensaeb
    llvm-6.0-runtime.binfmt  qemu-aarch64     qemu-hexagon     qemu-mips          qemu-mipsn32el  qemu-riscv32  qemu-sparc        register
    python2.7                qemu-aarch64_be  qemu-hppa        qemu-mips64        qemu-or1k       qemu-riscv64  qemu-sparc32plus  sbcl
    python3.6                qemu-alpha       qemu-m68k        qemu-mips64el      qemu-ppc        qemu-s390x    qemu-sparc64      status
    python3.7                qemu-arm         qemu-microblaze  qemu-mipsel        qemu-ppc64      qemu-sh4      qemu-xtensa
    

    现在我们可以运行 ARM 版本的 ubuntu:

    root@odysseus # docker run --rm -t arm64v8/ubuntu uname -m
    WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64) and no specific platform was requested
    aarch64
    

    由于主机CPU是AMD,因此可以预料到警告,可以通过将平台指定给docker来摆脱:

    root@odysseus # docker run --rm --platform linux/arm64 -t arm64v8/ubuntu uname -m
    aarch64
    

    这究竟是如何工作的?

    QEMU 的基础就是插入一个 DBM(动态二进制修改)解释器来将一个系统的指令集翻译成底层平台的指令集。

    我们唯一要做的就是告诉底层系统在哪里可以找到这些解释器。这就是qemu-user-static 图像在注册二进制格式魔术字符串/解释器时所做的。那么,那些binfmts 里有什么?

    root@odysseus # cat /proc/sys/fs/binfmt_misc/qemu-aarch64
    enabled
    interpreter /usr/bin/qemu-aarch64-static
    flags: F
    offset 0
    magic 7f454c460201010000000000000000000200b700
    mask ffffffffffffff00fffffffffffffffffeffffff
    

    嗯——这很有趣,尤其是因为在主机系统上没有/usr/bin/qemu-aarch64-static,而且它也不在目标图像中,那么这个东西在哪里?它在qemu-user-static 图像本身中,带有适当的表单标记:<HOST-ARCH>-<GUEST-ARCH>,如multiarch/qemu-user-static:x86_64-aarch64

    # Not on the local system
    odysseus % ls /usr/bin/qemu*
    ls: cannot access '/usr/bin/qemu*': No such file or directory
    
    # Not in the target image
    odysseus % docker run --rm --platform linux/arm64 -t arm64v8/ubuntu bash -c 'ls /usr/bin/qemu*'
    /usr/bin/ls: cannot access '/usr/bin/qemu*': No such file or directory
    
    # where is it?
    odysseus % docker run --rm multiarch/qemu-user-static:x86_64-aarch64 sh -c 'ls /usr/bin/qemu*'
    docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "sh": executable file not found in $PATH: unknown.
    # Hmm, no `sh` in that image - let's try directly...
    odysseus % docker run --rm multiarch/qemu-user-static:x86_64-aarch64 /usr/bin/qemu-aarch64-static --version
    qemu-aarch64 version 7.0.0 (Debian 1:7.0+dfsg-7)
    Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
    
    # AHA - there it is.
    

    这才是真正的魔法,我还不太明白。我相信,docker 不知何故使用该图像来启动 QEMU 解释器,然后将您要运行的实际图像/容器中的代码提供给它,就像前面的 uname 示例一样。一些网络搜索让我对这种魔法是如何实现的感到不满意,但我猜如果我继续关注这里的链接,我可能会找到这种轻微手的真正来源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-16
      • 1970-01-01
      • 2018-07-09
      • 2019-05-17
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多