Build Multi-Architecture Images through Jenkins Pipeline¶
In Jenkins, Podman is used as the tool for building images instead of Docker, primarily because Podman does not require mounting docker.sock and supports rootless mode, allowing it to run without root privileges, thus enhancing security.
In Jenkinsfile, you can directly use Docker or Podman commands; in most cases, they are the same. Currently, Podman has replaced Docker (alias docker=podman), so executing Docker commands will actually invoke Podman.
Prerequisites¶
Similar to Docker, Docker supports multi-platform builds, provided the host machine supports multi-platform builds using QEMU to emulate other platform environments. Before building multi-architecture images, you need to configure the following:
Configure binfmt_misc Module¶
Configure the binfmt_misc
module (mandatory). binfmt_misc
is a module in the Linux kernel that allows the kernel to recognize and execute binary files of a specified format. Since the binfmt_misc
module requires high privileges, root permissions are needed to operate it. Therefore, you must manually execute the following commands on all host machines running the Agent:
find /proc/sys/fs/binfmt_misc -type f -name 'qemu-*' -exec sh -c 'echo -1 > {}'
wget -O qemu-binfmt-conf.sh https://raw.githubusercontent.com/qemu/qemu/master/scripts/qemu-binfmt-conf.sh && chmod +x qemu-binfmt-conf.sh && ./qemu-binfmt-conf.sh --qemu-suffix "-static" --qemu-path "/usr/bin"
Install QEMU Binary Files¶
The base images provided in the workbench (base
, go
, nodejs
, python
, maven
) already include QEMU binaries, so no additional steps are needed.
If your Agent image is not one of the aforementioned base images, you can add QEMU binaries in one of the following ways:
-
Add QEMU installation commands in the Dockerfile
-
Directly add QEMU binaries to your Agent image using the following script
For more information on QEMU and binfmt_misc, refer to:
Build Multi-Platform Images¶
Podman is compatible with Dockerfile syntax but does not support the --platform
parameter in Dockerfile (i.e., it does not support cross-compilation). Instead, it uses QEMU to emulate other platform environments, which means the build process will be slower than Docker.
Podman does not support directly building images for multiple platforms in one go using --platform
. Instead, you need to build images for multiple platforms separately and then use Podman’s manifest
command to merge them. However, Podman supports adding images to a manifest conveniently by using the manifest parameter in the build command.
Using Dao-2048 image as an example, the Dockerfile is as follows:
FROM nginx # Ensure the base image supports multiple platforms if building multi-platform images
COPY . /usr/share/nginx/html
EXPOSE 80
CMD sed -i "s/ContainerID: /ContainerID: "$(hostname)"/g" /usr/share/nginx/html/index.html && nginx -g "daemon off;"
Specify Manifest Parameter When Building Image¶
Run the following commands in sequence:
target=release.daocloud.io/demo/dao-2048:v1 # (1)!
platform=linux/amd64,linux/arm64 # (2)!
docker build -f Dockerfile --platform=$platform --manifest release.daocloud.io/demo/dao-2048:v1 . # (3)!
docker login xxx # (4)!
docker manifest push --all $target # (5)!
- The final image name
- Platforms to be built
- Build multi-architecture image
- Log in to the container registry
- Push the image
The final built image will contain images for both amd64 and arm64 platforms:
Of course, if you directly use Docker commands in Jenkinsfile, which do not support the manifest parameter, you can achieve the same result by building images separately. The steps are as follows:
-
Build images for different platforms
-
Use podman manifest create to create a manifest image
-
Use podman manifest add to add images for different platforms to the manifest image
-
Use podman manifest push to push the manifest image to the container registry
Jenkinsfile Example¶
pipeline {
agent {
node {
label 'base'
}
}
stages {
stage('clone') {
agent none
steps {
container('base') {
git(branch: 'master', credentialsId: 'zxw-gitlab', url: 'https://gitlab.daocloud.cn/ndx/dao-2048.git')
}
}
}
stage('build & push') {
agent none
steps {
container('base') {
sh '''
pwd
ls -a
target=release.daocloud.io/demo/dao-2048:v1
platform=linux/amd64,linux/arm64
docker build -f Dockerfile --platform=$platform --manifest release.daocloud.io/demo/dao-2048:v1 .
docker manifest push --all $target
'''
}
}
}
}
}