compose icon indicating copy to clipboard operation
compose copied to clipboard

DOCKER_FALLBACK_PLATFORM environment variable

Open darkbasic opened this issue 1 year ago • 9 comments

Description

Lots of people started using Mac with M1/M2 chips for development work. When using Docker to run various containers (via docker-compose) you often have to modify the docker-compose.yml file to specify platform: linux/amd64 (and make sure the docker-compose.yml's version is at least 2.4).

Here is an example of the type of error message I frequently see:

Error response from daemon: image with reference phpmyadmin/phpmyadmin:5 was found but does not match the specified platform: wanted linux/arm64, actual: linux/amd64

Is there a way to have Docker / Docker Compose (on a Mac) try to use the linux/arm64 version, but if it's not available, automatically fall back to the linux/amd64 image?

Original question on stackoverflow: https://stackoverflow.com/questions/76220506/is-there-a-way-to-have-docker-on-mac-fallback-to-linux-amd64-when-a-linux-arm64

I don't use Macs but I have a similar issue with my Raptor CS Talos 2 ppc64le (IBM Power 9) workstation. Whenever available I want to use native ppc64le images but I'd like to automatically fallback to amd64 (which gets translated via qemu-user) when none is available. The env variable could be placed into .bashrc and forgot about and everything would automagically work.

darkbasic avatar May 18 '23 10:05 darkbasic

@n-rodriguez why would you think this is a bad feature to have? Committing a specific platform to your docker-compose.yml is not feasible because it will break it for your colleagues if they use a different architecture with native images available.

darkbasic avatar May 22 '23 15:05 darkbasic

why would you think this is a bad feature to have?

IMHO people should use/build multi-arch images.

n-rodriguez avatar May 22 '23 17:05 n-rodriguez

For this image specific, it looks like phpmyadmin/phpmyadmin is an old Docker Hub repository; https://hub.docker.com/r/phpmyadmin/phpmyadmin

Note that since phpMyAdmin has been accepted in to the official DockerHub repository, you can use either that or this older phpMyAdmin repository for your Docker installation. This is maintained as a courtesy to users who have not migrated.

The official image repository (phpmyadmin) is multi-arch, so should have native images available for all platforms; https://hub.docker.com/_/phpmyadmin

thaJeztah avatar May 22 '23 17:05 thaJeztah

For this image specific, it looks like phpmyadmin/phpmyadmin is an old Docker Hub repository

Sure, but that's just an example, in fact:

IMHO people should use/build multi-arch images

That's what we should ideally converge to, but have you ever tried using a ppc64le system? The vast majority of images are not supported on ppc64 and when they do they either don't support older versions or they do so via a different namespace (like ibm's) which makes it unsuitable for a team shared docker-compose.yml (I can make tons of examples, from mongo 3 to postgis to pgadmin4, etc, etc). Sometimes when performance is important and/or I am going to use an image alot I do even pull the image source code and build my own ppc64 image and/or even embed it in my project along with a vscode task to automatically build it. Unfortunately that's not always feasible, especially if you are contributing a patch to a random project and you just want to ensure that tests are passing.

qemu-user is a great way to get up to speed quickly and easily but you need a way to specify a fallback architecture to make it useful. This is no substitute to proper multi-arch images, but it's still very much needed.

darkbasic avatar May 22 '23 18:05 darkbasic

Such a feature in compose would make sense if docker run also has support for it, otherwise the user experience would be terribly confusing.

ndeloof avatar May 23 '23 05:05 ndeloof

@ndeloof I thought about that and while it would definitely come in handy it isn't as strictly necessarily because you can easily override the platform with a command line argument whenever it fails (at least that's what I do). On the other hand with docker compose you're forced to edit the configuration file (a command line argument wouldn't suffice because there might be multiple services in the same config) and I can't commit the changes whenever I work in a team. That being said it's still useful to have a similar feature in docker run so I will file another feature request there.

darkbasic avatar May 23 '23 05:05 darkbasic

I would really like this feature, running on mac M2 myself, my team is working on amd64 architecture. When performance is critical I rebuild a docker image myself for arm64, but in all other cases I'm fine with running amd64 images. We also have a lot of old images that are not going to be made multiarchitecture any time soon.

So currently I can either choose to rebuild all images that I need for arm64 architecture, or I need to run all images for amd64 architecture. That makes it impossible to rebuild performance critical images, unless I manually change the docker-compose file, which would make it harder to reuse that file with the team.

Currently I use this command: DOCKER_DEFAULT_PLATFORM=linux/amd64 docker compose up ..... but that means that all images need to be amd64. I will get an error for native arm64 images.

denisko avatar Sep 20 '23 08:09 denisko

The harsh reality is that a FALLBACK_PLATFORM variable is basically mandatory to develop in teams across different architectures. But I think we need yet another feature: the possibility to specify additional images in docker-compose.yml for otherwise unsupported architectures. For example mongodb official image does NOT support ppc64le and will likely never do (you can't say I didn't try), so I ended up creating my own: https://hub.docker.com/repository/docker/darkbasic/mongo-ppc64le/general I use that in my local docker-compose.yml but I can't force it down my team's throat by adding it to git because they are mostly on x86. For performance sensitive images where I can't use the hypothetical FALLBACK_PLATFORM variable I would love to be able to specify a fallback image for unsupported platforms directly in the docker compose config file.

darkbasic avatar Sep 20 '23 08:09 darkbasic

For that case, You can parameterise the image using either an env-var inside your compose file, and set that environment variable on your machine (or in .env for compose).

But if it's part of a docker build (or you're ok with "building" an image) you can either use a build-arg that (if set) overrides the default image;

# syntax=docker/dockerfile:1


ARG MONGO_IMAGE=mongo
ARG MONGO_VERSION=6.0

FROM ${MONGO_IMAGE}:$MONGO_VERSION AS mongodb
# .... etc

But if you want that to be handled automatically based on the hosts's platform, you can do something like this (unfortunately some amount of boilerplating; see https://github.com/moby/buildkit/issues/2618);

# syntax=docker/dockerfile:1

ARG MONGO_VERSION=6.0.9

# official mongodb image supports windows (amd64), linux (amd64 and arm64)
FROM mongo:${MONGO_VERSION} AS mongo-windows-amd64
FROM mongo:${MONGO_VERSION} AS mongo-linux-amd64
FROM mongo:${MONGO_VERSION} AS mongo-linux-arm64

# no official image for mongodb on ppc64le
FROM --platform=linux/ppc64le darkbasic/mongo-ppc64le:${MONGO_VERSION} AS mongo-linux-ppc64le


# select either the official image or our own build (for ppc64le) of mongodb
FROM mongo-${TARGETOS}-${TARGETARCH} AS mongodb


FROM mongodb AS final-stage
# if you don't need to do an actual build.. that's it; building this image
# basically just "aliases" the right variant. But you can add more steps
# here if you need a custom image with custom config.

By default, that will build an image for your native architecture, so users on a (for example) linux/amd64 machine (or Docker Desktop on a amd64 machine) will see;

docker build -t mymongo .
[+] Building 1.7s (7/7) FINISHED                                                                                                    docker:default
 => [internal] load build definition from Dockerfile                                                                                          0.1s
 => => transferring dockerfile: 815B                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                             0.1s
 => => transferring context: 2B                                                                                                               0.0s
 => resolve image config for docker.io/docker/dockerfile:1                                                                                    0.3s
 => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032edf31be0021               0.0s
 => [internal] load metadata for docker.io/library/mongo:6.0.9                                                                                0.4s
 => CACHED [mongo-linux-amd64 1/1] FROM docker.io/library/mongo:6.0.9@sha256:7dadc8a3463baf51be3ad4fa8e3fdbf019ee014c7e6383158a231c68827ec85b 0.0s
 => exporting to image                                                                                                                        0.0s
 => => exporting layers                                                                                                                       0.0s
 => => writing image sha256:533a6b306c665fcc8e7e0f6f944f6016fb7a9b36b5f6b6646bfd577dc5c507e8                                                  0.0s
 => => naming to docker.io/library/mymongo                                                                                                    0.0s

And users on a linux/ppc64le, or users on that set the --platform=linux/ppc64le option when building the image, will see;

docker build --platform=linux/ppc64le -t mymongo .
[+] Building 1.9s (7/7) FINISHED                                                                                                                          docker:default
 => [internal] load build definition from Dockerfile                                                                                                                0.0s
 => => transferring dockerfile: 815B                                                                                                                                0.0s
 => [internal] load .dockerignore                                                                                                                                   0.0s
 => => transferring context: 2B                                                                                                                                     0.0s
 => resolve image config for docker.io/docker/dockerfile:1                                                                                                          0.4s
 => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032edf31be0021                                     0.0s
 => [internal] load metadata for docker.io/darkbasic/mongo-ppc64le:6.0.9                                                                                            0.4s
 => CACHED [mongo-linux-ppc64le 1/1] FROM docker.io/darkbasic/mongo-ppc64le:6.0.9@sha256:ad95e33f9b2b6effad2b93fca2393cdad0fa9f8db2187d80d30e59e55634e0d4           0.0s
 => exporting to image                                                                                                                                              0.0s
 => => exporting layers                                                                                                                                             0.0s
 => => writing image sha256:e600735372feccec10b5b214edccddc9e372fe9e28f77ae37dcab67edfa11cf0                                                                        0.0s
 => => naming to docker.io/library/mymongo                                                                                                                          0.0s

And the mymongo image (what I named it when building) will be a ppc64le image;

docker image inspect --format='{{.Architecture}}' mymongo
ppc64le

thaJeztah avatar Sep 20 '23 09:09 thaJeztah