Choose the right tool for the task, they say. But how does one figure out what the right tool is? Or how long is one supposed to keep looking until they either get bored or over-engineer?
Questions everyone might ask. Is there a single way of tackling the problem? Hell no. The ration between exploration and implementation is every person’s preference. Both can benefit at different times and ideally having them both at the same time on the team.
Dockerized GitHub Runner
I needed to build a docker image of my telegram bot application for Raspberry PI (ARMv7). I wrote a pipeline in Azure DevOps and pushed the resulting image to Docker Hub. After I pulled it to my PI, I got a wrong format something error message which means the architecture is not matching.🤷♀️
First thing I learned was images are actually architecture-dependent. This has never occurred to me as I’ve always built x64 on x64 machines. As of today, it’s possible to build multi-arch images with Docker Desktop using experimental buildx command. See documentation and blog.
My idea was to let my PI build the bot’s image by itself for itself. There would be a container running DockerCLI communicating with the PI’s host and running GitHub’s runner that would get invoked by Github’s action upon merge into the main branch.
After two days back and forth, I had a docker image capable exactly of what I needed. Amazing. Here’s the project’s GitHub repo.

GitHub Actions
During wiring the runner into GitHub Actions, I stumbled on build-push-action repo and saw it uses buildx (!!!) and all the platforms can be defined on a single line.🙈

Just like that, it’s that easy:
# Credits: https://github.com/docker/build-push-action
name: Build and push from the main branch
on:
push:
branches: master
jobs:
multi:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm/v7,linux/arm64
push: true
tags: |
hubacekjirka/s3-telegram-uploader:latest
hubacekjirka/s3-telegram-uploader:1.0.0
Conclusion
It was a big face-palm moment when I found how a little piece of code I can simply reuse solves my problem. Shit happens …
Even the impassable paths shall be explored.
Free translation, Jára Cimrman
On the other hand, I got experience with GitHub runner wrote lines of bash scripts, wrote Dockerfile and did something that I or others can benefit in the future.
Leave a Reply