This repository contains code to create a docker image for a github action runner, and instructions for using it. The most useful guide I found was here and this repository is based on that.
I am targetting 64-bit (arm64 and x64), my use case is to be able to run GitHub Actions as self-hosted action runners. The environment that is built into docker images is:
- Architecture arm64 and x64
- Debian Bookworm
- Github Action Runner 2.311.0
- Additional packages
git
,gh
,docker-compose
In order to create the image the first time, you'll need to install docker, as per
this guide. Then download the repository
and build the image, assuming you are on arm64
. The ARCH value of arm
is also possible
if you are on ARM 32-bit:
[bash] git clone [email protected]:mutablelogic/docker-action-runner.git
[bash] cd docker-action-runner && RUNNER_ARCH="arm64"
[bash] docker build \
--tag "runner-image-${RUNNER_ARCH}" \
--build-arg RUNNER_VERSION="2.311.0" \
--build-arg RUNNER_ARCH="${RUNNER_ARCH}" \
-f Dockerfile-bionic .
Re-tag the image for uploading to docker (or whatever other registry service you're using) and push to that registry once you know it's worked:
[bash] RUNNER_ARCH="arm64" ORGANIZATION="mutablelogic" REGISTRY="ghcr.io/${ORGANIZATION}" \
IMAGE="runner-image-${RUNNER_ARCH}" VERSION=`git describe --tags`
[bash] echo "Push: ${REGISTRY}/${IMAGE}:${VERSION#v}"
[bash] docker login "${REGISTRY}"
[bash] docker tag "${IMAGE}" "${REGISTRY}/${IMAGE}:${VERSION#v}" && docker tag "${IMAGE}" "${REGISTRY}/${IMAGE}:latest"
[bash] docker push "${REGISTRY}/${IMAGE}:${VERSION#v}" && docker push "${REGISTRY}/${IMAGE}" && docker image rm "${IMAGE}"
At this point you would have your images in the registry ready for use. I also made the following changes on my Raspberry Pi:
- I added
cgroup_enable=memory
to the file/boot/cmdline.txt
and rebooted, so that nomad (see below) can use the memory cgroups support. You need to reboot the Raspberry Pi to make the changes take effect; - I downloaded and installed
libseccomp2_2.5.1-1_armhf.deb
from here which fixed an issue with building the container on ARM (changearmhf
toarm64
as necessary).
If you have a number of images with different architectures you want to combine into a single manifest, please see the GitHub Actions workflow below.
You then have a choice of running directly with docker or using an orchestration tool like Nomad. The environment variables you need to set in order to manage the runner environment are:
ORGANIZATION
: Where you're storing the runner image in the registry and the organization attached to the runner;ACCESS_TOKEN
: Create a personal access token in GitHub here. The token should haveadmin:org
permissions.NAME
: The name of the runner, which is used to identify it on GitHub (optional);LABELS
: Comma-separated labels for the runner (optional). These are in addition to the existing labelsself-hosted, linux, arm
or similar;GROUP
: The runner group. Set to 'Default' if not otherwise set.
If you're using Docker to create a runner action process, create a personal access token in GitHub here.
The token should have admin:org
permissions. The token should be set as an environment variable ACCESS_TOKEN
.
[bash] ORGANIZATION="mutablelogic" REGISTRY="ghcr.io/${ORGANIZATION}" ACCESS_TOKEN="XXXXXXX"
[bash] docker run --detach --name action-runner \
--env ORGANIZATION="${ORGANIZATION}" --env ACCESS_TOKEN="${ACCESS_TOKEN}" \
--env NAME="${HOSTNAME}" --env LABELS="" --env GROUP="" \
--volume /var/run/docker.sock:/var/run/docker.sock \
"${REGISTRY}/runner-image:latest"
[bash] docker logs -f action-runner
(If you have a previously running container, you can remove it first with docker stop action-runner && docker rm action-runner
).
When you see the line "Listening for Jobs" you can then scoot over to the GitHub Actions page to see that the runner is working.
The page will be https://github.com/organizations/${ORGANIZATION}/settings/actions/runners
Here is a typical nomad job file that will run the runner:
variable "access_token" {
type = string
}
variable "github_username" {
type = string
default = "djthorpe"
}
variable "organization" {
type = string
default = "mutablelogic"
}
variable "datacenters" {
type = list(string)
default = [ "10707" ]
}
variable "image" {
type = string
default = "ghcr.io/mutablelogic/runner-image"
}
job "action-runner" {
type = "system"
datacenters = var.datacenters
task "runner" {
driver = "docker"
env {
ORGANIZATION = var.organization
NAME = node.unique.name
LABELS = node.datacenter
ACCESS_TOKEN = var.access_token
}
config {
image = var.image
auth {
username = var.github_username
password = var.access_token
}
privileged = true
userns_mode = "host"
volumes = [
"/var/run/docker.sock:/var/run/docker.sock",
]
}
}
}
You'll need to have var.access_token
, defined elsewhere, for example you can invoke from the command line:
[bash] nomad job run \
-var -var access_token=${ACCESS_TOKEN} \
action-runner.hcl
Your configuration for Nomad may also need to be updated for docker:
plugin "docker" {
config {
allow_privileged = true
volumes {
enabled = true
}
}
}
Finally, you can then create a GitHub action which will build the images and a manifest, which is part of this repository here. These images are currently private but you can set up your own workflow or let me know and I can make the images visible to you.
Here are some references I found useful: