Skip to content

fix(docker): multi-arch image build (amd64+arm64) -- closes #223#445

Open
TheAuditorTool wants to merge 1 commit intoOWASP-Benchmark:masterfrom
TheAuditorTool:fix/multi-arch-docker
Open

fix(docker): multi-arch image build (amd64+arm64) -- closes #223#445
TheAuditorTool wants to merge 1 commit intoOWASP-Benchmark:masterfrom
TheAuditorTool:fix/multi-arch-docker

Conversation

@TheAuditorTool
Copy link
Copy Markdown

The published Docker image was linux/arm64 only because it was built on an ARM64 host. This caused >60s startup via QEMU emulation on amd64, breaking downstream CI (ZAP scans).

Changes:

  • VMs/buildDockerImage.sh: rewrite to use docker buildx with --platform linux/amd64,linux/arm64 for multi-arch manifest
  • VMs/Dockerfile: pin ubuntu:22.04, collapse RUN layers, add EXPOSE 8443 and CMD for usability
  • .github/workflows/docker-publish.yml: add CI workflow for automated multi-arch builds (workflow_dispatch only -- inactive until secrets and triggers are configured)
  • PR_multi-arch-docker.md: changelog, guide, and activation steps

Summary

The published owasp/benchmark:latest Docker image was built on an ARM64 host,
making it linux/arm64 only. On amd64 machines (the vast majority of CI runners
and developer workstations), Docker falls back to QEMU emulation, causing
startup times over 60 seconds -- long enough to break downstream CI (e.g., ZAP
scans reported in #223).

This PR switches the build tooling from docker build to docker buildx build
with --platform linux/amd64,linux/arm64. Docker Hub receives a single manifest
list that serves the native image for each architecture automatically.


What Changed

VMs/Dockerfile

Change Why
FROM ubuntu:latest -> FROM ubuntu:22.04 Pin the base image for reproducible builds. latest silently rolls forward and has caused breakage before.
Collapsed 3 separate RUN apt-get layers into 1 Fewer layers = smaller image. Single RUN also ensures apt-get update and install share the same cache.
Added rm -rf /var/lib/apt/lists/* Standard practice -- drops the apt cache from the final layer.
Collapsed BenchmarkUtils clone + build into 1 RUN Fewer layers.
Collapsed BenchmarkJava clone + CVE-2022-24765 workaround + build into 1 RUN Fewer layers, keeps related steps together.
Collapsed useradd + chpasswd into 1 RUN Fewer layers.
Added EXPOSE 8443 Documents the port Benchmark listens on (Cargo/Tomcat). Informational only -- does not affect runtime behavior.
Added CMD ["./runBenchmark.sh"] Container now starts the benchmark when run without arguments, instead of doing nothing.
Removed trailing whitespace on the useradd line Housekeeping.

VMs/buildDockerImage.sh

Complete rewrite. The old script ran docker build -t benchmark . which
produces a single-architecture image matching the build host.

The new script:

  1. Creates (or reuses) a docker buildx builder instance named
    benchmark-multiarch.
  2. Runs docker buildx build --platform linux/amd64,linux/arm64 --push which
    builds for both architectures and pushes a manifest list to Docker Hub in
    one atomic step.

Important: --push is required because multi-arch manifest lists cannot be
loaded into the local Docker daemon. The build and push happen together.

.github/workflows/docker-publish.yml (NEW -- INACTIVE)

A GitHub Actions workflow that automates the multi-arch build and push.
This workflow is set to workflow_dispatch only -- it will never run
automatically until you activate it.
See the activation section below.


How to Use the Build Script (Manual Build)

Prerequisites: Docker with buildx support (Docker Desktop 19.03+ or Docker
Engine with the buildx plugin). You must be logged in to Docker Hub:

docker login -u <your-dockerhub-username>

Then, from the VMs/ directory:

cd VMs
./buildDockerImage.sh

This builds for both amd64 and arm64 and pushes owasp/benchmark:latest to
Docker Hub. No separate docker push step is needed.


How to Activate the GitHub Actions Workflow

The workflow file is already in place at
.github/workflows/docker-publish.yml, but it will only run when manually
triggered via the GitHub UI. To make it fully automatic:

Step 1: Add Docker Hub Secrets

Go to Settings > Secrets and variables > Actions in your GitHub repository
and add:

Secret name Value
DOCKERHUB_USERNAME Your Docker Hub username
DOCKERHUB_TOKEN A Docker Hub access token (create one at https://hub.docker.com/settings/security)

Step 2: Add Automatic Triggers

Open .github/workflows/docker-publish.yml and uncomment the trigger lines:

on:
  workflow_dispatch:
  # Uncomment these when ready:
  push:
    branches: [master]
    paths: ['VMs/Dockerfile']
  release:
    types: [published]

This will automatically rebuild and push the image whenever:

  • The Dockerfile is changed on master, or
  • A new GitHub release is published.

Step 3: Test with Manual Trigger

Before enabling automatic triggers, test the workflow manually:

  1. Go to Actions > Docker Publish in your repository
  2. Click Run workflow
  3. Verify the image appears on Docker Hub with both architectures

You can confirm multi-arch support with:

docker manifest inspect owasp/benchmark:latest

This should show entries for both amd64 and arm64.


What Was NOT Changed

Item Reason
JDK version (17) Tracked separately in #227
bench:bench user/password This is a test image, not a production deployment
timeout 60 ./runBenchmark.sh; exit 0 warm-up trick Functional and intentional -- caches runtime dependencies in the image

…chmark#223

The published Docker image was linux/arm64 only because it was built on
an ARM64 host. This caused >60s startup via QEMU emulation on amd64,
breaking downstream CI (ZAP scans).

Changes:
- VMs/buildDockerImage.sh: rewrite to use docker buildx with
  --platform linux/amd64,linux/arm64 for multi-arch manifest
- VMs/Dockerfile: pin ubuntu:22.04, collapse RUN layers, add
  EXPOSE 8443 and CMD for usability
- .github/workflows/docker-publish.yml: add CI workflow for
  automated multi-arch builds (workflow_dispatch only -- inactive
  until secrets and triggers are configured)
- PR_multi-arch-docker.md: changelog, guide, and activation steps
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant