14

It has been mentioned that when employing x86_64 Docker images on an M1 Mac, when no ARM64 image is available, that container will start under qemu emulation for compatibility. (At the cost of performance.)

Often times when I'm running a collection of containers (and integration tests against the lot), I'll see qemu-system-aarch64 pegging a few cores.

My question: How can I determine, for a given list of running containers (ie. docker ps), which ones are running natively and which are being emulated?

Craig Otis
  • 31,257
  • 32
  • 136
  • 234
  • Have no hardware to find by myself but I think there might be something related in `docker inspect`. If you know for sure that a certain container is being emulated, can you do `docker inspect container_id` on it? Then we can see if it's possible to show emulation with `docker ps`. – anemyte Apr 03 '21 at 10:44

2 Answers2

23

This is true also for Docker running on amd64 CPU, when the image is build for arm64, and the whole mechanism is explained in this SO

The mechanism for emulation is using the information in the elf to recognize the architecture for which the process is build, and if the architecture of the binary differs from the architecture of the CPU, it starts the qemu emulation. Though the recognizing of the architecture is more related to the process, there is still information about the targeted architecture of the docker image. The targeted architecture is determined from the "Architecture" flag on the image which was set when the image was build. Any of the containers that will run the image will be associated (trough the image) with this flag.

It should be noted that the "Architecture" flag on the image will not prevent a single process inside the image, which is compiled for a different architecture than the flagged one to run. The reason for this is that bitfmt (which is the underlying mechanism sitting inside the linux kernel) will always try to recognize the architecture from the magic numbers of the elf and will start the the emulation if the magic number is recognized.

To list the architecture of the containers, you can use the following "quick" query:

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

The command will print the container name, the architecture and the os of the image.

To avoid typing this command multiple times, you can add alias in .bashrc as follows:

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

After this, you can use simple docker-arch-ps to get the list of the containers and their architecture.

jordanvrtanoski
  • 5,104
  • 1
  • 20
  • 29
  • 1
    Thanks for the answer! It was very informative and learned something new: processes inside container can be of different architecture. Expanding on this, can I query/see somehow which processes inside the running container are of different architecture? Mostly for Docker on Mac I'm interested. – foobarna Jan 17 '22 at 16:36
  • 1
    The `file` command followed by a name will show you what type of file it is. For ELF files (unix executable binaries), the command also shows for which architecture the file is build. You can use combination of `find` and `file` utilities to try to identify the binary architecture. – jordanvrtanoski Jan 18 '22 at 09:41
3

As an improvement of the @jordanvrtanoski's answer, I've done two additional commands

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'

and 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'

They produce outputs close to the original commands and support options of docker container ls and 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: the column command used here is the one from 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).

Pascal H.
  • 1,431
  • 8
  • 18
  • 1
    `column` does not support long options on macOS nor on the Linux boxes I tried. – konrad Mar 27 '22 at 15:34
  • It depends if you use `column` from BSD or from util-linux. The one from `util-linux` supports long options and is more recent. To get it on macOS, you should use `brew install util-linux`; on rockylinux, the default version seems to be the one from `util-linux` and unfortunately Debian/Ubuntu have chosen the opposite (cf https://askubuntu.com/q/1098248). NB: util-linux is a standard package distributed by the Linux Kernel Organization for use as part of the Linux operating system (cf https://github.com/util-linux/util-linux and its link on Wikipedia) – Pascal H. Mar 28 '22 at 10:10
  • I add my remark as PS in my answer to be more explicit. – Pascal H. Mar 28 '22 at 10:18
  • Thanks for the clarification. Unfortunately, even if you install `util-linux`, it is keg-only and will not be available on you path by default, so you need to replace it with `/opt/homebrew/opt/util-linux/bin/column`. Nevertheless, these utils are very useful now that they work and I will remove the downvote. – konrad Mar 29 '22 at 12:18
  • what a great answer - thank you for putting these commands together! – Aaron V Jul 01 '22 at 02:32