在 Docker 中使用 Qemu 的困惑

在 Docker 中使用 Qemu 的困惑

我目前正在学习在 x86 主机上构建 ARM Docker 映像。我发现本指南,以及其他几个基本上都说了同样的事情。它们都是几年前的了,所以这个问题的答案可能是 Qemu 或 Docker 不再以那种方式工作了,但我无法验证这一点。

基本上,你必须做两件事:

  1. 安装qemu-user-binfmt软件包。这将创建一个名为/proc/sys/fs/binfmt_misc/qemu-arm以下内​​容的文件:

    enabled
    interpreter /usr/bin/qemu-arm-static
    flags: OCF
    offset 0
    magic 7f454c4601010100000000000000000002002800
    mask ffffffffffffff00fffffffffffffffffeffffff
    
  2. 安装qemu-user-static软件包以获取/usr/bin/qemu-arm-static解释器。这将删除以前的软件包,但binfmt-entry 将保留。


然后指南继续说,为了构建 ARM 映像,您必须将步骤 2 中的解释器复制到映像中系统上的相同位置,并且为了运行 ARM 映像,您必须使用选项挂载这两个副本-v /usr/bin/qemu-arm-static:/usr/bin/qemu-arm-static

为了测试这一点,我创建了两个图像和,qemu-test以及qemu-test:noqemu以下 Dockerfiles(我将解释器复制到我的工作目录中):

qemu-test

FROM armv7/armhf-ubuntu

COPY qemu-arm-static /usr/bin

CMD ["sh", "-c", "echo 'Hello World'"]

qemu-test:noqemu

FROM armv7/armhf-ubuntu

CMD ["sh", "-c", "echo 'Hello World'"]

然后我尝试了以下四个命令(仍然在我的 x86 机器上):

docker run qemu-test
docker run -v /usr/bin/qemu-arm-static:/usr/bin/qemu-arm-static qemu-test
docker run qemu-test:noqemu
docker run -v /usr/bin/qemu-arm-static:/usr/bin/qemu-arm-static qemu-test:noqemu

令我惊讶的是,他们都工作了。只要binfmt-entry 存在,就是这样。当我删除它时,它们都不起作用。我还在 ARM 机器上运行了这两个图像,它们也都正常工作。

这让我想到了我的问题:将解释器放入镜像中有什么实际意义?安装它有什么意义?我到底需要 Qemu 吗?请记住,这些指南已经有好几年了。如果答案确实是“东西不再那样运作了”,那么我也会对它现在的运作方式感兴趣。

答案1

binfmt_misc 内核模块配置中有一个重要字段,即标志F。该标志表示无论挂载命名空间如何,解释器的路径都是固定的。否则,当遇到似乎适用于另一个平台的文件时,binfmt 将在与/usr/bin/qemu-arm-static您尝试运行的命令相同的挂载命名空间中查找解释器(),您将收到错误file not found

安装的一部分qemu-user-static是运行update-binfmts需要该--fix-binary标志的程序包。这通常在较新版本的软件包中完成,以处理 docker 用例,但如果您使用的是旧版本,则会遇到类似以下问题此错误报告描述了

正确配置后,我为其他平台构建镜像的首选方法是使用 buildkit,docker 可以使用其 buildx CLI 来实现这一点。使用 buildkit,您可以获得变量来选择各个阶段的平台(使用本机平台下载一些二进制文件然后将它们复制到目标镜像可能会更快)。有关 buildx 的更多信息,请参阅docker 的文档

相关内容