Is it possible to push docker images for different architectures separately? - docker

From what I know docker buildx build --push will overwrite existing image architectures with the one you specified in --platform parameter. As I understand you have to build and push for all architectures at the same time when using buildx. However, I know that official docker images use arm64 build farm to build linux/arm64 images. How is it possible? Do they just use docker push without buildx? If so, does it mean docker push doesn't overwrite existing architectures unlike buildx? What's the best way to do that if I want to build and push multiple architectures on separate machines?

You can build and push with separate commands on different hosts in a cluster, each sending to a different tag. And then after all tags for each platform have been pushed, you can use docker manifest to create a multiplatform manifest that points to all images with a single tag. This tool currently requires experimental support to be enabled.
Further details on docker manifest can be found in the docs: https://docs.docker.com/engine/reference/commandline/manifest/

Related

Docker Buildx - Building multi-platform images much slower than single platform

We have been using docker build for our images.
The build takes place using Jenkins slave on ec2 amd64.
docker build .
The build takes around 5 minutes.
However, now when using docker buildx --platform linux/amd64, linux/arm64.
The build takes much longer around 30 minutes.
From what I understood, it's because the node is amd64 and it's using an emulator for building the arm64.
How can we make it faster?
We are having npm install command in our dockerfile and some shell commands.
If you can run that command from an arm64 ec2 instance, like Graviton, it will run MUCH faster. When we build multi-arch images on arm64 we can build in a matter of minutes, but when doing the same thing on amd64, it can take well over half an hour depending on the image. arm64 chips seem to be able to handle the multi-arch builds much better than amd64, unfortunately.
Another option besides running docker buildx from a single host, is to build both images on their native architectures quickly, push the resulting containers to the repo and then push the manifest to combine them into a multi-arch container. For larger builds this may be the way to go instead of waiting forever for a build to finish.
Sample Refs:
https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-multi-architecture-image.html
https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/

docker buildx disable parallel build for multiplatform

I have a docker build that during the build needs to run the server for some admin configuration. By running the server it claims a port and during multi-platform build this conflicts with the docker buildx command as it claims that the port is already in use.
Now I would like to run the build sequentially instead of in parallel but that does not seem to be an option?
I've tried to make this work by setting the cpus to 1 (--cpuset-cpus 1) but that does not seem to make a difference.
docker buildx build --platform=linux/amd64,linux/arm64/v8 --cpuset-cpus 1 --push -t ivonet/payara .
from git repo https://github.com/IvoNet/docker-payara
I'm working on an Apple M1 (aarch64)
So is it possible to run this build with parallel disabled?
I've done a bit of research on it now and I have not found a satisfactory answer other than that it does not seem to be possible at this time to disable the parallelism.
I did find a workaround that works for me and steps nicely around this issue.
I now use actual remote servers to build the target platforms I need.
In essence, one defines a remote (through ssh) server with docker installed on it and you configure it to build specific targets.
That way it can actually run in parallel as the physically different machines can handle the formally overlapping port number (as was the problem in my use case).
Read the full blog post on it here

How to push multiple digest with different OS/ARCH under one tag in docker?

I am relatively new to docker and saw in other repositories that we can push multiple digests under same tag with different OS/ARCH in docker. For example:
How can I achieve the same? Right now whenever I do docker push [REPO_LINK] from different architectures, it replaces the last pushed one with it's architecture. Thanks!
You might be looking for fat manifest aka manifest list.
It enables building images with multiple architectures under same tag. You need to use docker manifest command, when using multiple machines.
Once you have pushed images from different machines, you have to finally combine the manifests of these images into single one (called as manifest list). See more from official docs.
This blog post was already mentioned in one comment, but you can still use that docker manifest example to combine manifests to single file, even if you are not working only on one machine.
Related question: Is it possible to push docker images for different architectures separately?
There are two options I know of.
First, you can have buildx run builds on multiple nodes, one for each platform, rather than using qemu. For that, you would use docker buildx create --append to add the additional nodes to the builder instance. The downside of this is you'll need the nodes accessible from the node running docker buildx which typically doesn't apply to ephemeral cloud build environments.
The second option is to use the experimental docker manifest command. Each builder would push a separate tag. And at the end of all those, you would use docker manifest create to build a manifest list and docker manifest push to push that to a registry. Since this is an experimental feature, you'll want to export DOCKER_CLI_EXPERIMENTAL=enabled to see it in the command line. (You can also modify ~/.docker/config.json to have an "experimental": "enabled" entry.)

Is a Docker Hub Repository only for a single Docker File or multiple Docker FIles

Is a Docker Hub Repository only for a single Docker File or multiple Docker Files ?
I am unclear, in my case in my have two repositories one for an Intel build (using Automated Build), and another for an Arm build of the same application that I had to build locally and push to Docker Hub.
Is that how you are meant to do it ?
With multi architecture & manifest it's possible to have many images for many architecture sharing the same tag.
I already answer one of your other post with this link : https://blog.slucas.fr/blog/docker-multiarch-manifest-hub-2/
Check this docker image, you can do a docker pull seblucas/alpine-homeassistant:latest for armhf, arm64 and amd64 without any problem (and each architecture will get its own image). The same is true for many other images provided by docker (alpine for example).
Yes, you can have multiple Dockerfiles in a repository, by using tags. Each tag corresponds to a Dockerfile, so you could two tags one called :intel and another one called :arm in the same repository.

How to automate Multi-Arch-Docker Image builds

I have dockerized a nodejs app on github. My Dockerfile is based on the offical nodejs images. The offical node-repo supports multiple architectures (x86, amd64, arm) seamlessly. This means I can build the exact same Dockerfile on different machines resulting in different images for the respective architecture.
So I am trying to offer the same architectures seamlessly for my app, too. But how?
My goal is automate it as much as possible.
I know I need in theory to create a docker-manifest, which acts as a docker-repo and redirects the end-users-docker-clients to their suitable images.
Docker-Hub itself can monitor a github repo and kick off an automated build. Thats would take care of the amd64 image. But what about the remaining architectures?
There is also the service called 'TravisCI' which I guess could take care of the arm-build with the help of qemu.
Then I think both repos could then be referenced statically by the manifest-repo. But this still leaves a couple architectures unfulfilled.
But using multiple services/ways of building the same app feels wrong. Does anyone know a better and more complete solution to this problem?
It's basically running the same dockerfile through a couple machines and recording them in a manifest.
Starting with Docker 18.02 CLI you can create multi-arch manifests and push them to the docker registries if you enabled client-side experimental features. I was able to use VSTS and create a custom build task for multi-arch tags after the build. I followed this pattern.
docker manifest create --amend {multi-arch-tag} {os-specific-tag-1} {os-specific-tag-2}
docker manifest annotate {multi-arch-tag} {os-specific-tag-1} --os {os-1} --arch {arch-1}
docker manifest annotate {multi-arch-tag} {os-specific-tag-2} --os {os-2} --arch {arch-2}
docker manifest push --purge {multi-arch-tag}
On a side note, I packaged the 18.02 docker CLI for Windows and Linux in my custom VSTS task so no install of docker was required. The manifest command does not appear to need the docker daemon to function correctly.

Resources