【问题标题】:How to determine when Docker containers (on an M1 MacBook) are running via qemu?如何确定 Docker 容器(在 M1 MacBook 上)何时通过 qemu 运行?
【发布时间】:2021-03-27 18:38:57
【问题描述】:

mentioned 在 M1 Mac 上使用 x86_64 Docker 映像时,当没有可用的 ARM64 映像时,该容器将在 qemu 仿真下启动以实现兼容性。 (以性能为代价。)

当我运行容器集合(以及针对该批次的集成测试)时,我经常会看到 qemu-system-aarch64 与几个核心挂钩。

我的问题:对于给定的运行容器列表(即docker ps),我如何确定哪些是本机运行的,哪些是模拟的?

【问题讨论】:

  • 我自己找不到硬件,但我认为docker inspect 中可能有相关内容。如果你确定某个容器正在被模拟,你可以在上面做docker inspect container_id 吗?然后我们可以看看是否可以使用docker ps 显示仿真。

标签: macos docker qemu apple-silicon


【解决方案1】:

对于在amd64 CPU 上运行的 Docker 也是如此,当映像是为arm64 构建时,整个机制是explained in this SO

模拟的机制是使用elf 中的信息来识别为其构建进程的体系结构,如果二进制的体系结构与CPU 的体系结构不同,它将启动qemu 模拟。虽然架构的识别与过程更相关,但仍然有关于 docker 镜像的目标架构的信息。目标架构由构建映像时设置的映像上的“架构”标志确定。将运行映像的任何容器都将(通过映像)与此标志相关联。

应该注意的是,映像上的“架构”标志不会阻止映像内部的单个进程,该进程编译为与标记的架构不同的架构运行。这样做的原因是bitfmt(这是位于 linux 内核中的底层机制)将始终尝试从elf 的magic 数字识别架构,如果magic 将启动仿真号码被识别。

要列出容器的架构,您可以使用以下“快速”查询:

for i in `docker ps --format "{{.Image}}"` ; do docker image inspect $i --format "$i -> {{.Architecture}} : {{.Os}}" ;done

该命令将打印镜像的容器名称、架构和操作系统。

为避免多次输入此命令,您可以在.bashrc 中添加别名,如下所示:

alias docker-arch-ps='for i in `docker ps --format "{{.Image}}"` ; do docker image inspect $i --format "$i -> {{.Architecture}} : {{.Os}}" ;done';

之后,您可以使用简单的docker-arch-ps 来获取容器列表及其架构。

【讨论】:

  • 感谢您的回答!它提供了非常丰富的信息并学到了一些新东西:容器内的进程可以具有不同的架构。对此进行扩展,我能否以某种方式查询/查看正在运行的容器中的哪些进程具有不同的架构?我对 Mac 上的 Docker 很感兴趣。
  • file 命令后跟名称将显示它是什么类型的文件。对于 ELF 文件(unix 可执行二进制文件),该命令还显示文件是针对哪个体系结构构建的。您可以结合使用find 和file 实用程序来尝试识别二进制架构。
【解决方案2】:

作为对@jordanvrtanoski 答案的改进,我做了两个额外的命令

docker-ps-arch:

#!/bin/bash
OPT=$@
set -euo pipefail
docker container ls $OPT --format "{{.ID}}\t{{.Image}}\t{{.Command}}\t{{.Status}}\t{{.Names}}" |
 awk -F '\t' 'BEGIN {OFS=FS} { "docker image inspect --format \"{{.Os}}/{{.Architecture}}\" "$2" #"NR | getline $6; print }' |
 column --table --table-columns "CONTAINER ID,IMAGE,COMMAND,STATUS,NAME,ARCH" -o '   ' -s $'\t'

和 docker-images-arch:

#!/bin/bash
OPT=$@
set -euo pipefail
docker image ls $OPT --format "{{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}" |
 awk -F '\t' 'BEGIN {OFS=FS} { "docker image inspect --format \"{{.Os}}/{{.Architecture}}\" "$3" #"NR | getline $5; print }' |
 column --table --table-columns "REPOSITORY,TAG,IMAGE ID,SIZE,ARCH" -o '   ' -s $'\t'

它们产生接近原始命令的输出并支持docker container ls 和docker image ls 的选项。

$ docker-ps-arch -a
CONTAINER ID   IMAGE          COMMAND    STATUS                         NAME               ARCH
261767e38db2   hello-world    "/hello"   Exited (0) About an hour ago   practical_moore    linux/amd64
16e364572d08   18e5af790473   "/hello"   Exited (0) 3 hours ago         peaceful_lalande   linux/arm64

PS:这里使用的column 命令是来自util-linux 的命令,而不是来自BSD utils 的命令。 util-linux 是 Linux 内核组织分发的标准包。在 macOS 上,要获取它,请使用 brew install util-linux; rockylinux 默认使用它,不幸的是,在 Debian/Ubuntu 上,已经做了相反的选择(cf https://askubuntu.com/q/1098248)。

【讨论】:

  • column 在 macOS 和我试过的 Linux 机器上不支持长选项。
  • 这取决于你使用的是来自 BSD 还是来自 util-linux 的 column。来自util-linux 的那个支持长选项并且是更新的。要在 macOS 上获取它,您应该使用 brew install util-linux;在rockylinux 上,默认版本似乎是来自util-linux 的版本,不幸的是Debian/Ubuntu 选择了相反的版本(参见askubuntu.com/q/1098248)。注意:util-linux 是由 Linux Kernel Organization 分发的标准软件包,用作 Linux 操作系统的一部分(参见 github.com/util-linux/util-linux 及其在 Wikipedia 上的链接)
  • 为了更加明确,我将我的评论添加为 PS。
  • 感谢您的澄清。不幸的是,即使您安装了util-linux,它也只是小桶,默认情况下不会在您的路径上可用,因此您需要将其替换为/opt/homebrew/opt/util-linux/bin/column。尽管如此,这些实用程序现在非常有用,我将删除反对票。
猜你喜欢
  • 2021-12-16
  • 2021-10-19
  • 2022-10-15
  • 2022-06-13
  • 2021-09-10
  • 2021-04-03
  • 1970-01-01
  • 2021-09-08
  • 2021-07-31
相关资源
最近更新 更多