Docker: Exporting Image for Multiple Architectures

Viewed 117

I have a scenario where I need to bundle a multi-container system in an exportable, transportable format. Specifically, I need to get an image from Docker Hub and store it on portable media (e.g. USB drive) that I can then load into an air-gapped machine with no internet access.

I can normally do this with:

# On the development server
docker pull nginx:1.23
docker save -o nginx.tar nginx:1.23

... store the .tar on portable media...

# On the air-gapped machine
docker load < myimage.tar

However, although the image is built for and supports multiple architectures, this appears to only store the image for a single architecture (the architecture of the machine that ran the docker pull). I need it to export images for all architectures to .tar files, so they can be loaded on machines of any architecture.

I've tried:

docker pull --platform linux/amd64 nginx:1.23
docker pull --platform linux/arm64 nginx:1.23

To manually specify that both the amd64 and arm64 images should be pulled, but the docker save still exports only a single image (which we can tell from the fact that the manifest.json file only has a single entry).

I've also tried:

docker pull --platform linux/amd64 --platform linux/arm64 nginx:1.23

But it has the same result.

How can I export/save an image with support for multiple different architectures when I docker load it? Ideally, I'd be able to docker load a single .tar file on a machine of any supported architecture, have it import the image for that architecture, then run the image.

EDIT:

After some further testing, I've found that if I do the following:

docker pull --platform linux/amd64 nginx:1.23
docker save -o nginx.tar

Then the .tar file has a manifest.json with a single image (for amd64). However, if I do this:

docker pull --platform linux/arm64 nginx:1.23
docker save -o nginx.tar

Then the .tar file has a manifest.json with two images (for amd64 and arm64).

This isn't an issue with "you have to pull both" though; if I pull the amd64 version again, and docker save again, we're back to a single image in the manifest.json. The order of pulls does appear to matter.

1 Answers

From my post on the vastly superior DevOps SE:

This is answered in the Docker blog post on multi-platform docker builds. For your specific situation, you would perform a build and push for each platform you'd like, then create a manifest file and push that. Then you can perform the save. It would look something like this:

$ docker buildx build --platform linux/amd64 --push -t localhost:5000/myimage:amd64 .
$ docker buildx build --platform linux/arm64 --push -t localhost:5000/myimage:arm64 .
$ docker manifest create myimage:latest myimage:amd64 myimage:arm64
$ docker manifest push localhost:5000/myimage:latest
$ docker image save -o myimage.tar localhost:5000/myimage:latest
Related