-
Notifications
You must be signed in to change notification settings - Fork 18.9k
Description
As mentioned in #33850, we're building support to be able to run images from multiple platforms (Linux & Windows) managed by a single Moby engine. This would need some changes to the CLI & APIs to make sure that the user can choose between platforms on a per-container basis when there is a multiarch image available such as microsoft/dotnet
Running Containers
In this proposal docker run should support running multiple platforms on a single machine.
Both of these would work on a Windows node:
docker run -it alpine /bin/bash
docker run -it microsoft/nanoserver powershell.exe
Neither of these are multi-arch images, so the OS will be determined from the image metadata.
API
The HostConfig definition is used in /containers/create, and already includes the
isolation parameter. The proposal is to add a new property platform.
Building containers
In this proposal, docker build would use the same --platform parameter as docker run to override platform when needed.
API
/containers/build doesn't use HostConfig as /containers/create does, so platform needs to be added to the call.
Choosing the platform & multi-arch images
Multi-arch images bring an extra layer of complexity to the build and run actions. If
the image has a multi-arch manifest, then there's a chance the node could run multiple images.
Here's a decision tree for how the platform is determined for a build or run action:
- Runtime parameter -
docker build --platform=...ordocker run --platform=... - Infer from Dockerfile & image metadata -
FROM microsoft/windowsservercoreorFROM alpineor other image - If single-arch, use
Image.Osfrom image definition
- If not in daemon's
PlatformCapabilitylist, fail - Note: You can also use a specific
image:tagto force the platform this way
- If multi-arch, then
- Use default container platform from daemon config
DefaultPlatform - If not configured, then
DefaultPlatform=OSTypefrom daemon
Example - Building a Windows container
In the simple case, the platform will be chosen based on the FROM image.
For this Dockerfile:
FROM microsoft/windowsservercore:10.0.14393.976
...And this build command:
docker build .- On a Windows host, the image runs as normal. Metadata matches host OS
- On a Linux host, the image platform != host platform. Pull of
microsoft/windowsservercorefails
Example - Building a Linux container
FROM alpine:latest
...docker build .- On a Windows host,
alpineis pulled and stored to disk- As the container is started, Hyper-V isolation uses the default Linux runtime to run the container
- On a Linux host, the image platform != host platform. Pull of
microsoft/windowsservercorefails
Recommendations for build & dev tools
Many tools such as IDEs, CI/CD pipelines, and more need to be able to handle building either
type of container. Here's a few proposed best practices to make automation work well.
Dockerfile
- If a project will only ever target a single OS, use the most restrictive
FROMstatementFROM alpineFROM microsoft/dotnet:alpineFROM microsoft/dotnet:nanoserver
- If it will be multiarch, use
FROMa multiarch image
docker build/run
- Single arch - (optional) specify
--platform=... - Multi arch - use multiple build/run commands with different
--platform=...parameters
Pulling & importing containers
The same api /images/create is used for both operations. The same order of precedence
as build and run should be followed to figure out which specific image to pull.
When pulling an image from a repo, the metadata includes the platform.
However, in the case of docker import this metadata is not known. The default should be
the platform of the host, but can be overridden with --platform.
Note: Windows doesn't support
docker importtoday at all
Examples:
docker pull --platform linux microsoft/dotnet-runtime will force pulling the Linux
version of this multiarch image.
docker import --platform linux dotnet-runtime.tgz would force importing to use the
Linux platform image store.