Johnny boy
Johnny boy

Reputation: 303

Github actions runner environment doesn't build for arm images

I get this error on my github build:

The requested image's platform (linux/arm/v7) does not match the detected host platform (linux/amd64) and no specific platform was requested

The runner environment I'm using is the ubuntu:latest and my container uses arm32v7/node base image.

Here's my Dockerfile:

FROM arm32v7/node AS appbuild
WORKDIR /app
COPY package.json ./
COPY src/ ./src
RUN npm install

FROM appbuild as release
ENTRYPOINT ["npm", "start"]

And here's my deployment to github yaml:

jobs:
  docker:
    runs-on: ubuntu-latest

The jobs are ran inside a ubuntu runner environment. I suspect the arm version of the node image I'm using is unable to run in that environment, is that correct?

Edit:

  - name: Build controller image
    if: steps.changed-files-plantcontroller.outputs.any_changed == 'true'
    run: >
      docker build -t ${{ env.image_name_controller }} ${{ env.context }}
    env:
      context: ./controller

Upvotes: 4

Views: 7607

Answers (1)

cam
cam

Reputation: 5218

You are correct. Docker on your arm64 build environment cannot build the arm32v7 image without Docker Buildx. You can solve this by using the buildx Github Action and qemu action, that prepares your environment to build multi-arch images.

Buildx is Docker's technology to build images for a target architecture not matching the host's (in this case the host arch is arm64). You can read about how this works here.

QEMU is an emulator used by Docker buildx. It's a dependency I learned the hard way was needed when writing a multi-arch workflow.

For more reference, check out this doc: https://github.com/docker/build-push-action/blob/master/docs/advanced/multi-platform.md

You should be able to build your image with a workflow with something like this:

name: ci

on:
  push:
    branches:
      - 'master'

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up QEMU dependency
        uses: docker/setup-qemu-action@v1
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      - name: Build controller image
        if: steps.changed-files-plantcontroller.outputs.any_changed == 'true'
        uses: docker/build-push-action@v2
        with:
          context: ${{ env.context }}
          tags: ${{ env.image_name_controller }}
          platforms: linux/arm/v7
          push: true
        env:
          context: ./controller

NOTE: Updated the last build command with how you have your Build controller image step written. It just translates the Docker command to how the Docker build-push-action builds.

An alternative command you could use in place of the build-push-action@v2:

docker buildx build -t ${{ env.image_name_controller }} --platform linux/arm/v7 --push ${{ env.context }}

The command assumes you want to push to a GitHub repo with the tag.


Unrelated, but there's an opportunity to simplify your Dockerfile.

When you're using buildx, Docker can handle pulling the right arm32v7 version of the image when the image you're pulling has multiple versions. Check out the node image tags and you'll see linux/arm/v7 listed as one of the OS/Arch tags. What this means is you could simplify your FROM arm32v7/node AS appbuild line to FROM node AS appbuild if you think you want to build for a different architecture sometime.

For example:

  • Github workflow that builds for amd64 and arm64
  • Dockerfile that pulls relevant amd64 or arm64 image depending on TARGETPLATFORM

Upvotes: 8

Related Questions