首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在构建容器之前,运行多重结构/qemu-用户-静态程序会做什么?

在构建容器之前,运行多重结构/qemu-用户-静态程序会做什么?
EN

Stack Overflow用户
提问于 2022-05-31 07:58:09
回答 2查看 959关注 0票数 2

谁能简单地解释一下

代码语言:javascript
运行
复制
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -c yes

在执行docker build之前,调用Dockerfile中的容器时做什么?

我的概念是允许将来自其他体系结构的容器使用到X86体系结构中,但我不太明白我在某些站点中找到的解释。

上述指令(docker run)的存在是否意味着构建阶段的Dockerfile用于另一个体系结构?

EN

回答 2

Stack Overflow用户

发布于 2022-07-06 21:48:45

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

设置和测试

每次重新启动系统都需要设置一次,其神奇之处就是:

代码语言:javascript
运行
复制
# 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

请注意,该测试示例假设您运行的是您自己的“无根”docker,因此它是以您自己的身份运行,而不是以root (或通过sudo)的身份运行,而且它的工作原理非常好。

血淋淋的细节

..。如果您想要了解,了解是如何/为什么工作的,那么哪些内容很重要。

这些信息的主要来源:

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

代码语言:javascript
运行
复制
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

启动(根的) dockerd并设置格式之后:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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来消除:

代码语言:javascript
运行
复制
root@odysseus # docker run --rm --platform linux/arm64 -t arm64v8/ubuntu uname -m
aarch64

这到底是怎么回事?

在此基础上,QEMU能够插入DBM (动态二进制修改)解释器,将一个系统的指令集转换为底层平台的指令集。

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

代码语言:javascript
运行
复制
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中一样。

代码语言:javascript
运行
复制
# 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示例所示。一些网络搜索让我无法满足于这个魔法是如何实现的,但我猜想,如果我继续跟踪链接从这里,我可能会找到真正的来源,轻微的手。

票数 5
EN

Stack Overflow用户

发布于 2022-10-13 07:29:51

为了补充@crimson的回答:fix-binary标志在binfmt_misc中被用来使静态编译的qemu模拟器在不同的名称空间/色度/容器中工作。

文档 for binfmt_misc中,您可以找到fix-binary标志的解释:

F- fix二进制 binfmt_misc的通常行为是在调用misc格式文件时懒洋洋地生成二进制文件。但是,面对挂载名称空间和变更,这并不能很好地工作,因此F模式在模拟安装后立即打开二进制文件,并使用打开的映像生成仿真器,这意味着无论环境如何更改,一旦安装,它总是可用的。

这个错误报告还解释了:

..。binfmt的fix-二进制标志是专门用来处理这个问题的。解释器文件(例如qemu静态)是在安装binfmt规则时加载的,而不是在遇到需要它的文件时加载的。当内核遇到一个需要解释器的文件时,它只是执行已经打开的文件描述符,而不是打开一个新的文件描述符(IOW:内核已经打开了正确的文件描述符,因此可能不同的根在查找解释器时不再发挥作用,从而允许像本机那样运行外部架构的名称空间/容器/色度)。

如果使用不带-p yes选项的qemu -user静态映像,将不会添加fix-binary标志,运行arm64容器将无法工作,因为现在内核实际上将尝试在容器的根文件系统中打开qemu模拟器:

代码语言:javascript
运行
复制
$ docker run --rm --privileged multiarch/qemu-user-static --reset
[...]

$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64-static
flags:
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff

$ 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
exec /usr/bin/uname: no such file or directory
failed to resize tty, using default size
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72444103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档