When you use Microsoft-hosted Linux agents, you can create Linux container images for the x64 architecture only (no ARM, no x86).

In order to create IoT Edge modules for other architectures (i.e. ARM), you can use a machine emulator such as QEMU.

Here there is how.

First of all, let’s create a Azure DevOps Pipeline based on the following YAML schema:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
#Exporting the module version from module.json for Docker Image Module versioning
- script: |
    echo '##vso[task.setvariable variable=moduleversion]'$(jq -r .image.tag.version $(System.DefaultWorkingDirectory)/edgeSolution/modules/mymodule/module.json)
        
- task: Bash@3
  inputs:
    targetType: 'inline'
    script: 'sudo apt update && sudo apt install qemu-user-static -y'

- task: Bash@3
  inputs:
    targetType: 'inline'
    script: 'sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset'

#Copying the qemu-arm-static Intel binary in the root folder of my module (where the Dockerfile.arm32v7 is located)
- task: Bash@3
  inputs:
    targetType: 'inline'
    script: 'sudo cp /usr/bin/qemu-arm-static $(System.DefaultWorkingDirectory)/edgeSolution/modules/mymodule/'

#A Dockerregistry service connection should be created before this step runs
#More info here: https://aka.ms/adoserviceconnection
- task: Docker@2
  displayName: Login to ACR
  inputs:
    command: login
    containerRegistry: myazurecontainerregistry

#This will build and push the myazurecontainerregistry.azurecr.io/myrepo:0.1.12-arm32v7 Docker image
- task: Docker@2
  inputs:
    command: 'buildAndPush'
    Dockerfile: 'edgeSolution/modules/mymodule/Dockerfile.arm32v7'
    buildContext: 'edgeSolution/modules/mymodule/'
    containerRegistry: 'myazurecontainerregistry'
    repository: 'myrepo'
    tags: '$(moduleversion)-arm32v7'

Now that you have the pipeline ready, there is only one thing you need to add in your Dockerfile.

That thing is the step for copying the qemu binary in the /usr/bin folder of your base image.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
FROM microsoft/dotnet:2.1-sdk AS build-env
WORKDIR /app

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

FROM microsoft/dotnet:2.1-runtime-stretch-slim-arm32v7
WORKDIR /app
COPY --from=build-env /app/out ./
COPY qemu-arm-static /usr/bin

RUN useradd -ms /bin/bash moduleuser
USER moduleuser

ENTRYPOINT ["dotnet", "mymodule.dll"]

That’s it! You are ready to trigger your pipeline and build the ARM Docker image for your IoT Edge Solution.

azure devops pipeline arm build positive result