As docker image already become norm these days, multiplatform image is inevitable. What is multiplatform image? Multiplatform image can be pulled by many systems in single tag, so intead using :someversion-arm64 tag or :someversion-amd64 we can :someversion tag only.
Before buildx intoduced there is also some hacky way, to made this happed, lets call it manifest manipulation, in this method image created and pushed separately then manipulating the manifest of docker image tag, making it conjunct/referencing with the image build separately.
Build Flows:
Dockerfile
ARG ARCH=
FROM ${ARCH}debian:latest
RUN apt update && apt install -y python3-minimal && apt clean && rm -rf /var/lib/apt/lists/* && mkdir /data
WORKDIR /data
CMD ["python3","-m","http.server"]
Building the images
$ docker build -t registry-url/application-name:tag-amd64 --build-arg ARCH=amd64/ .
$ docker build -t registry-url/application-name:tag-arm32v7 --build-arg ARCH=arm32v7/ .
$ docker build -t registry-url/application-name:tag-arm64v8 --build-arg ARCH=arm64v8/ .
Pushing the images
$ docker push registry-url/application-name:tag-amd64
$ docker push registry-url/application-name:tag-arm32v7
$ docker push registry-url/appplication-name:tag-arm64v8
Here we had 3 images, with 3 different manifest, then we create a new manifest by using the other images manifest.
Create manifest
$ docker manifest create \
registry-url/application-name:tag-latest \
--amend docker push registry-url/application-name:tag-amd64 \
--amend registry-url/application-name:tag-arm32v7 \
--amend registry-url/appplication-name:tag-arm64v8
Lastly we push the tag-latest manifest,
Push manifest
$ docker manifest push registry-url/application-name:tag-latest
The current way is using buildx, by using buildx build docker images become simpler but also need to pay attention few things.
In simple terms:
docker run --rm --privileged tonistiigi/binfmt:latest -install all
docker buildx create --name MultiArch
docker buildx use MultiArch
docker buildx build --push --platform linux/amd64,linux/arm64 -t registry-url/application-name:tag-latest .
What exactly happen?
MultiArchMultiArchlinux/amd64,linux/arm64 and with tag registry-url/application-name:tag-latestLet we see more details:
First we run the tonistiigi/binfmt:latest
Then create our builder
dedyms@homelab docker-gitlab-local % docker buildx create --name MultiArch
MultiArch
Remember our Dockerfile before? we need to remove the ARCH
FROM debian:latest
RUN apt update && apt install -y python3-minimal && apt clean && rm -rf /var/lib/apt/lists/* && mkdir /data
WORKDIR /data
CMD ["python3","-m","http.server"]
Now lets build the image:
oh my gosh i forgot run docker buildx use MultiArch
Lets run it again: progressing....
finished
Now lets inspect the image, here im using the image that already pushed, you may replace the registry-url/application-name:tag-latest to yours
dedyms@homelab apptest % docker buildx imagetools inspect martadinata666/python-http-server:latest
Name: docker.io/martadinata666/python-http-server:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:447c287bcea699a7403990d9a75b4553e91d4dcc9ba0241bdb50c94e8d26f1e0
Manifests:
Name: docker.io/martadinata666/python-http-server:latest@sha256:d1ab736ab3b53005fce1161474716b152749bff4aa56d9cc490c7187ce59a9f1
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
Name: docker.io/martadinata666/python-http-server:latest@sha256:3dcef16799d429101ee2a04690d3720e88c7e2919a6621e43a7e4b8f9072fb25
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
sources: