Using GitHub Actions to build ARM-based Docker Images

Kevin Mansel
Apr 15 · 6 min read
Image for post
Image for post
Using GitHub Actions to build ARM-based Docker Images

Hi everyone. I tend to play around with my Raspberry PI from time to time, and recently I set off on a task to build out an ARM-based Docker Image that I could run on my PI for an IoT project. I figured hey, it would be great to have a nice CD process to build the image once I merged my code into my master branch on GitHub. Well hello, GitHub Actions.

Actions are GitHub’s answer to the CI/CD software workflow process. Actions can do a ton of things, and there is a great marketplace that already has quite a few actions to choose from. So let’s get started.

There are a few things we’re going to need:

  • A GitHub account
  • A container registry to push our images to
  • An IDE to write some code

I personally am going to use Azure Container Registry for this example, and I use VSCode as my IDE.

Let’s make a quick Node application that will run a webserver and say hello. This is a quick and easy express server. Just going to output a general message and log to the console the requesting IP address.


‘use strict’; 

Now it’s time to make our Dockerfile. Notice that we want to build this image from the ARM version for node.


FROM arm32v7/node 

So we now have our Dockerfile and our node application that we want to package up into an image. The last piece we need to write up is our GitHub Action. When you’re structuring your repository, the GitHub Actions need to be put into a specific directory .github/workflows/

Image for post
Image for post
All workflows for GitHub need to be in the .github/workflows/ directory

You can name your workflow whatever you’d like, here you can see that I have labeled mine dockerimage.yml


name: Docker Build/Publish Image 

There is a lot going on here. So let's break it down a bit.

Here we are saying, please run this workflow when we push code to our master branch. Since you’re an amazing developer and you’re following best practices, you only push to master once your CI process and testing have passed…so for this action, we want to fire off the building of our docker image when new code is pushed to our master branch.

branches: [ master ]

In this section, we are setting up some environment variables to use through the rest of the Action. As you can see, I’ve got my registry and image name I want to use. I’m importing my username and password from my secrets vault within GitHub. You can find that in the “Settings” tab under the “Secrets” blade. I’m also setting the target platform I want my image to build which is linux/arm/v7

runs-on: ubuntu-18.04
DOCKER_IMAGE: kmansel/express-me
Image for post
Image for post
You can set secrets through GitHub in your vault. Follow “Settings” -> “Secrets”

The first step that we want to run is to check out the code from the repo, this will bring our codebase into our build environment for GitHub Actions.

- name: Checkout the code       
uses: actions/checkout@v1

We now need to pull in an Action that will give us the ability to run the dockerx command. This is the command that will allow us to build our ARM-based image. Thanks to GitHub user crazy-max for building this action and sharing it with the world:

- name: Set up Docker Buildx      
uses: crazy-max/ghaction-docker-buildx@v1
version: latest

Here we are preparing some local variables for our docker commands to use. You’ll also notice the if: success() command here. This will make sure the previous step has completed successfully before moving to this step. You can see here we are referencing some of the environment variables we set at the beginning of the Action. You’ll notice I’m setting my version variable to ${GITHUB_RUN_NUMBER} This is a variable that is available to us as a default environment variable by GitHub Actions. You can read more about default environment variables that are available here:

- name: Prepare      
if: success()
id: prepare
run: |
echo ::set-output name=docker_platform::${DOCKER_TARGET_PLATFORM}
echo ::set-output name=docker_image::${DOCKER_REGISTRY}/${DOCKER_IMAGE}
echo ::set-output name=version::${GITHUB_RUN_NUMBER}

Our final two steps are to login to your registry using the docker login command and then build/push our desired image to this registry. You can see that we are using our variables from our prepare step in the docker buildx command.

- name: Docker Login      
if: success()
run: |
echo "${DOCKER_PASSWORD}" | docker login ${DOCKER_REGISTRY} --username "${DOCKER_USERNAME}" --password-stdin

You should be able to see your action progress through the steps live on GitHub. As you can see in the image, I’ve scrolled to the part where the output logs are showing that we have in fact pushed the docker image to the repository.

Image for post
Image for post
Viewing a GitHub Actions workflow live!

Ok, we see that it’s been pushed to the registry here, but I need proof. Let's head over to the container registry and see if we’ve got an image up there.

Image for post
Image for post
Look at that…an ARM-based docker image. :)

Awesome! So now you know that it’s possible to build ARM-based docker images through the GitHub workflow engine. This should get you on your way to a solid CD process for deploying containers to Raspberry PI ARM-based platforms. I personally used this pattern to push my images and pull them down to a Raspberry PI via Azure IoT Hub service.

Hope this helps you in your development journey.

Thanks for reading!

The Startup

Medium's largest active publication, followed by +733K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store