Skip to content
Latchkey

How to Build a Multi-Arch Docker Image in a Jenkins Pipeline

Drive docker buildx from a Jenkins stage to cross-build amd64 + arm64 into one pushed manifest.

On an agent with Docker and Buildx, register QEMU emulators, create a builder, log in with bound credentials, then docker buildx build --platform ... --push.

Buildx in a stage

Install emulators, create a builder, then build both platforms and push under the build number tag.

Jenkinsfile
pipeline {
  agent any
  stages {
    stage('Build multi-arch') {
      steps {
        withCredentials([usernamePassword(credentialsId: 'registry-creds',
          usernameVariable: 'REG_USER', passwordVariable: 'REG_PASS')]) {
          sh '''
            echo "$REG_PASS" | docker login -u "$REG_USER" --password-stdin registry.example.com
            docker run --privileged --rm tonistiigi/binfmt --install all
            docker buildx create --use
            docker buildx build \
              --platform linux/amd64,linux/arm64 \
              -t registry.example.com/myorg/app:${BUILD_NUMBER} \
              --push .
          '''
        }
      }
    }
  }
}

Gotchas

  • The agent needs Docker with Buildx and the ability to run a privileged container for QEMU registration.
  • Buildx pushes the multi-platform manifest directly; you cannot load it into the agent's local daemon.
  • Use triple single-quotes for the shell block so Groovy does not interpolate $REG_USER before the shell sees it.

Verify it actually works

Validate the pipeline definition against the running controller before committing. Jenkins parses declarative pipelines strictly, and a syntax error surfaces as a failed build rather than a clear parse message.

Terminal
# validate a Jenkinsfile against the live controller
curl -X POST -F "jenkinsfile=<Jenkinsfile" \
  https://your-jenkins/pipeline-model-converter/validate

# replay a build with modified script to test a change without committing
# Build page -> Replay -> edit -> Run

Agent and workspace assumptions that break in CI

  • An agent label that matches no online agent leaves the build queued indefinitely rather than failing.
  • Workspaces are reused between builds by default, so stale files from a previous run can mask or cause failures. Use cleanWs() or a fresh workspace when correctness matters.
  • Tools resolved from the controller PATH are not necessarily on the agent PATH. Declare them in a tools block or install them in the pipeline.
  • Credentials bound with withCredentials are masked in logs but still visible to any process you launch; avoid passing them as command-line arguments.

Frequently asked questions

How do I build a Multi-Arch Docker Image in a Jenkins Pipeline?
On an agent with Docker and Buildx, register QEMU emulators, create a builder, log in with bound credentials, then docker buildx build --platform ... --push.
Buildx in a stage?
Install emulators, create a builder, then build both platforms and push under the build number tag.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card