Skip to main content

Multi-Arch Docker Image

This tutorial explains how to build and publish multi-arch docker image

Build with QEMU

The simplest approach is to build with QEMU on a single node. Firstable you will need to set up the machine running OneDev server or agent where you plan to build the image (or host machine if OneDev runs inside container):

  1. Install QEMU with below command:

    docker run --privileged --rm tonistiigi/binfmt --install all
  2. Now set up the project in OneDev to build image with above builder, and specify platforms option. This is demonstrated with the example project:

    • Enable package management feature in general setting of the example project so that it can be used as image repository. This is not necessary if you push images to third party registry
    • The docker file simply prints current platform into a file
    • Check step build and push image of the ci job:
      • Property Tags uses variables to push to current server and project, tagged with current build number
      • Property Built-in Registry Access Token Secret in more settings specifies a secret with permission to publish packages to current project
      • Property Platforms in more settings specifies platforms to build
  3. Run the job, and we can see that a multi-arch image is published

Build on Native Platform

The QEMU approach is simple, but can be slow. Also it may not be able to handle complex builds relying heavily on platform specific features. In this case, you will need to resort to the native platform approach, which build separate image on each platform, and combine them into a single multi-arch image index with docker imagetools. We also created an example project demonstrating this:

  1. Enable package management feature in general setting of the example project so that it can be used as image repository. This is not necessary if you push images to third party registry

  2. The docker file simply prints current platform into a file

  3. Job build arch images builds platform specific image:

    • It define a param arch including enum value amd64 and arm64

    • Job executor is specified as @param:arch@ meaning to run with job executor named by the arch parameter. On this demo site, we simply define two server docker executors with name amd64 and arm64. For real world projects, you will need to run OneDev agents on amd64 and arm64 machines, and define amd64/arm64 executor as remote docker executor selecting amd64/arm64 agents respectively

    • Step build arch image builds image with property Platform set to linux/@param:arch@ and More Options set to --metadata-file meta.json (both properties are in more settings section):

      • Option --metadata-file writes image medata into a file which we will extract manifest digest from later
      • The Platform property does not have to be specified for real world project, as running on specific platform will generate image for that platform automatically. We use it here as all platform builds of the demo project are actually running with server docker executor
    • Step create digest file extracts image manifest digest from metadata file exported above, and create an empty file named by the digest

    • Step publish digest file publishes the digest file generated by above step

  4. Job create image index collects digests of all platform images and calls docker imagetools to create an image index in registry:

    • It declares a job dependendy to build arch images, and passes value amd64 and arm64 for param arch, and then retrieve all published artifacts of the dependency job, which is the digest file
    • The step prepare image sources prefixes each image manifest digest with registry repository and prints them to a single file named sources
    • The step create image index calls buildx imagetools command to create image index in docker registry using content of file sources
  5. Run job create image index, and it will trigger two instances of job build arch images, one for amd64 param value, and another for arm64. After platform images being published, it continues to create index from these images and generate a multi-arch image successfully