如何通过 qemu 确定 Docker 容器(在 M1 MacBook 上)何时是 运行?

How to determine when Docker containers (on an M1 MacBook) are running via qemu?

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

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

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

amd64 CPU 上 Docker 运行ning 也是如此,当图像是为 arm64 构建时,整个机制是

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

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

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

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

该命令将打印容器名称、体系结构和图像的os。

为避免多次输入此命令,您可以在.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 来获取容器列表及其架构。

作为对@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}}\" "" #"NR | getline ; 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}}\" "" #"NR | getline ; print }' |
 column --table --table-columns "REPOSITORY,TAG,IMAGE ID,SIZE,ARCH" -o '   ' -s $'\t'

它们产生接近原始命令的输出并支持 docker container lsdocker 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 not the one from BSD utils. util-linux is a standard package distributed by the Linux Kernel Organization. On macOS, to get it, use brew install util-linux; rockylinux uses it by default and unfortunately on Debian/Ubuntu, the opposite choice has been done (cf https://askubuntu.com/q/1098248).