Push multiple docker images to manifest without tags
Here's the solution I came to -- though for most people the added steps and workarounds here are unnecessary when compared to Jean's answer. You should go with that answer unless you specifically need what mine provides.
I wanted to run the builds on different machines -- an arm box and an amd64 box -- to achieve better build speeds than qemu could provide. However, GitLab / GitHub runners can't communicate with each other, so I couldn't use buildx's ability to run on multiple machines natively. What I came up with was to build the images, push them to an intermediate registry (or export & import them locally if no registry is avaliable was available), pull & use them as cache for another final buildx.
Something like this in GitLab CI:
# Build your images separately however you need, tagging with -${arch}# Do testing on the image to make sure it validates, then...deploy_image: stage: deploy script: - > for arch in "amd64 arm64 armv7"; do export name="$<YOUR CONTAINER URL AND TAG>-${arch}" docker pull "NAME" # or `docker load` export ARCH_IMAGES_CACHE="$ARCH_IMAGES_CACHE --cache-from $NAME" done # Docker will detect that the images we pulled are entirely cacheable, and use those without building - docker buildx build --push --pull $ARCH_IMAGES_CACHE --build-arg BUILDKIT_INLINE_CACHE=1 --platform="linux/amd64,linux/arm64,linux/arm/v7" -t "$<YOUR CONTAINER URL>:${CI_COMMIT_SHORT_SHA}" .
There are probably better methods or abstractions that could be done using docker manifest
or docker buildx imagetools
, but this was the best solution I came up with.
You want to build multi-arch images and it can be done using buildx (assuming they share the same dockerfile in the current directory):
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t yourorg/your-image-name:r1234 --push .
On Gitlab-CI this should look like this :
variables: DOCKER_HOST: tcp://docker:2375/ DOCKER_DRIVER: overlay2services: - docker:dindbuild-multi-arch-images: stage: build-images image: jdrouet/docker-with-buildx:stable script: - docker buildx create --use - docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t yourorg/your-image-name:r1234 --push .stages: - build-images
Then for r1234-gui I would suggest a second dockerfile using this trick at the top:
ARG MYAPP_IMAGE=yourorg/your-image-name:latestFROM $MYAPP_IMAGE
Which will allow you to provide MYAPP_IMAGE as a command line paramether:
docker buildx build -f yourdockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t yourorg/your-image-name:r1234-gui --build-arg MYAPP_IMAGE=yourorg/your-image-name:r1234 --push .