Good with a keyboard and fluent in gibberish

Container Platforms

Nobody actually defines what the container platform strings are, and how they overlap. I went splunking so you don’t have to.

Background

Part of the container specification is the idea of “platforms”–operating system and CPU architecture in a neat little package. They show up in a bunch of places if you go looking: docker run has a --platform, you can say FROM --platform in your Dockerfile (in buildx), the docker github actions often have platforms inputs/outputs, etc.

It’s also very common to install qemu to allow transparent (if not slow) cross-platform container building, either through a system package (as I’ve discussed before), or as a CI/CD step (eg docker/setup-qemu-action).

However, none of the documentation actually tells you what these strings are, so you’re left wondering what linux/amd64/v3 is and should you build it separately.

The Story

So if you check the buildx CLI argument documentation, specifically docker buildx build --platform, it’ll tell you that it’s defined in the containerd source code.

And if you go check the containerd source code, you’ll see it says some things about slashes but that the values ultimately come from GOARCH and GOOS.

And then if you go searching, you might find the go build instructions which include the list of valid values for Architecture, OS, & Variant, as well as the valid combinations.

The basic format is <OS>/<ARCH> or <OS>/<ARCH>/<VARIANT>, but many inputs will accept just <OS> or <ARCH>.

The Table

The main part of the platform is os/arch, which describe the OS and CPU the container is valid for. I’ve made a lovely table of which ones are available and where they’re valid.

OS 386 amd64 arm arm64 loong64 mips mips64 mips64le mipsle ppc64 ppc64le riscv64 s390x wasm
aix                          
android                    
darwin                        
dragonfly                          
freebsd                      
illumos                          
ios                          
js                          
linux  
netbsd                      
openbsd                    
plan9                      
solaris                          
wasip1                          
windows                    

(Sorry about the table, mobile users. Hopefully I’ll improve it later.)

Additionally, containerd documents these aliases:

Alias Real
aarch64 arm64
armhf arm/v7
armel arm/v6
i386 386
x86_64 amd64
x86-64 amd64
macos darwin

Variants

Additionally, a number of architectures define variants–usually instruction set enhancements, but sometimes things like floating point handling. These are mostly copied directly from the go docs. There’s often backwards compatibility, but not universally.

Also, the default when building varies. Sometimes it’s autodetected, sometimes it’s minimum.

If anyone has references to how containers handle backwards compatibility or default variants, let me know.

386

  • softfloat: use software floating point operations; should support all x86 chips (Pentium MMX or later).
  • sse2: use SSE2 for floating point operations; has better performance but only available on Pentium 4/Opteron/Athlon 64 or later.

arm

  • v5: use software floating point; when CPU doesn’t have VFP co-processor
  • v6: use VFPv1 only; default if cross compiling; usually ARM11 or better cores (VFPv2 or better is also supported)
  • v7: use VFPv3; usually Cortex-A cores

amd64

  • v1: The baseline. Exclusively generates instructions that all 64-bit x86 processors can execute
  • v2: all v1 instructions, plus CMPXCHG16B, LAHF, SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3
  • v3: all v2 instructions, plus AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, OSXSAVE
  • v4: all v3 instructions, plus AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL

mips, mips64, mipsle, mips64le

  • hardfloat: use floating point instructions
  • softfloat: use soft floating point

ppc64, ppc64le

  • power8: ISA v2.07
  • power9: ISA v3.00

riscv64

  • rva20u64: only use RISC-V extensions that are mandatory in the RVA20U64 profile
  • rva22u64: only use RISC-V extensions that are mandatory in the RVA22U64 profile
  • rva23u64: only use RISC-V extensions that are mandatory in the RVA23U64 profile

wasm

Unlike all the other architectures, wasm variants are a comma separated list of additional experimental features:

  • satconv: saturating (non-trapping) float-to-int conversions
  • signext: sign-extension operators