Run Docker based GitHub runner containers on Azure Container Instances (ACI)

pwd9000

Marcel.L

Posted on June 17, 2022

Run Docker based GitHub runner containers on Azure Container Instances (ACI)

Overview

All the code used in this tutorial can be found on my GitHub project: docker-github-runner-windows or docker-github-runner-linux.

Welcome to Part 4 of my series: Self Hosted GitHub Runner containers on Azure.

In the previous part of this series, we looked at how we can use CI/CD in GitHub using GitHub Actions to build our docker containers and then push the docker images to an Azure Container Registry (ACR) we created in Azure.

Following on from the previous part we will now look at how we can use Azure Container Instances (ACI) to run images from the remote registry.

I will cover two scenarios, first how we can run self hosted GitHub runner as as an Azure Container Instances (ACI) from our images using using Azure-CLI, and second how we can use CI/CD workflows in GitHub using GitHub Actions to deploy our ACIs.

Pre-Requisites

Things we will need are:

  • Create an ACI deployment Resource Group
  • Grant access to our GitHub Service Principal created in Part3 of this blog series on the Resource Group to create ACIs

For this step I will use a PowerShell script, Prepare-RBAC-ACI.ps1 running Azure-CLI, to create a Resource Group and grant access to our GitHub Service Principal App we created in the previous blog post (Part 3).



#Log into Azure
#az login

# Setup Variables.
$aciResourceGroupName = "Demo-ACI-GitHub-Runners-RG"
$appName = "GitHub-ACI-Deploy" #Previously created Service Principal (See part 3 of blog series)
$region = "uksouth"

# Create a resource group to deploy ACIs to
az group create --name "$aciResourceGroupName" --location "$region"
$aciRGId = az group show --name "$aciResourceGroupName" --query id --output tsv

# Grant AAD App and Service Principal Contributor to ACI deployment RG
az ad sp list --display-name $appName --query [].appId -o tsv | ForEach-Object {
    az role assignment create --assignee "$_" `
        --role "Contributor" `
        --scope "$aciRGId"
}


Enter fullscreen mode Exit fullscreen mode

As you can see the script has created an empty resource group called: Demo-ACI-GitHub-Runners-RG, and gave our GitHub service principal Contributor access over the resource group.

image.png

NOTE: Ensure that the GitHub Service Principal also has AcrPush permissions on the Azure Container Registry (ACR). See Part3 of this series, or you can use the following PowerShell snippet:



#Log into Azure
#az login

# Setup Variables. (provide your ACR name)
$appName="GitHub-ACI-Deploy"
$acrName="<ACRName>"
$region = "uksouth"

# Create AAD App and Service Principal and assign to RBAC Role to push and pull images from ACR
$acrId = az acr show --name "$acrName" --query id --output tsv
az ad sp create-for-rbac --name $appName `
    --role "AcrPush" `
    --scopes "$acrId" `
    --sdk-auth
```

![image.png](https://raw.githubusercontent.com/Pwd9000-ML/blog-devto/main/posts/2022/GitHub-Docker-Runner-Azure-Part4/assets/rbac03.png)

### Deploy ACI - Azure-CLI

Next we will deploy a self hosted GitHub runner as an **Azure Container Instance (ACI)** using **Azure-CLI**.

Get the relevant image details from the **Azure Container Registry**:

![image.png](https://raw.githubusercontent.com/Pwd9000-ML/blog-devto/main/posts/2022/GitHub-Docker-Runner-Azure-Part4/assets/acr-lin02.png)

For this step I will use a PowerShell script, [Deploy-ACI.ps1](https://github.com/Pwd9000-ML/docker-github-runner-linux/blob/master/Azure-Pre-Reqs/AzureContainerInstance/Deploy-ACI.ps1)

```powershell
#az login

#Variables
$randomInt = Get-Random -Maximum 9999
$aciResourceGroupName = "Demo-ACI-GitHub-Runners-RG" #Resource group created to deploy ACIs
$aciName = "gh-runner-linux-$randomInt" #ACI name (unique)
$acrLoginServer = "registryname.azurecr.io" #The login server name of the ACR (all lowercase). Example: _myregistry.azurecr.io_
$acrUsername = "servicePrincipalClientId" #The `clientId` from the JSON output from the service principal creation (See part 3 of blog series)
$acrPassword = "servicePrincipalClientSecret" #The `clientSecret` from the JSON output from the service principal creation (See part 3 of blog series)
$image = "$acrLoginServer/pwd9000-github-runner-lin:2.293.0" #image reference to pull
$pat = "githubPAT" #GitHub PAT token
$githubOrg = "Pwd9000-ML" #GitHub Owner
$githubRepo = "docker-github-runner-linux" #GitHub repository to register self hosted runner against
$osType = "Linux" #Use "Windows" if image is Windows OS

az container create --resource-group "$aciResourceGroupName" `
    --name "$aciName" `
    --image "$image" `
    --registry-login-server "$acrLoginServer" `
    --registry-username "$acrUsername" `
    --registry-password "$acrPassword" `
    --environment-variables GH_TOKEN="$pat" GH_OWNER="$githubOrg" GH_REPOSITORY="$githubRepo" `
    --os-type "$osType"


Enter fullscreen mode Exit fullscreen mode

NOTE: Remember when we ran our docker containers in part one and two of this series we had to pass in some environment variables using the '-e' option to specify the PAT (Personal Access Token), GitHub Organisation and Repository to register the runner against. We pass these values in using the '--environment-variables' parameter as show above.

See creating a personal access token on how to create a GitHub PAT token. PAT tokens are only displayed once and are sensitive, so ensure they are kept safe.

The minimum permission scopes required on the PAT token to register a self hosted runner are: "repo", "read:org":

image.png

Tip: I recommend only using short lived PAT tokens and generating new tokens whenever new agent runner registrations are required.

After running this command, under the GitHub repository settings, you will see a new self hosted GitHub runner. (This is our Azure Container Instance):

image.png

You will also see the ACI under the resource group we created earlier:

image.png

You can simply re-run the above script to add more runners and ACIs. To stop and remove the ACI container you can run:



az container delete --resource-group $aciResourceGroupName --name $aciName


Enter fullscreen mode Exit fullscreen mode

Next we will look at how we can use CI/CD in GitHub to deploy ACIs using GitHub Actions

Deploy ACI - GitHub CI/CD

Because we have our repository already set up with the relevant Service Principal and GitHub Secrets from the previous blog post:

image.png

We can create a GitHub Workflow to deploy our Azure Container Instances. deployACI-Lin.yml



name: Deploy_GHRunner_Linux_ACI

on:
  workflow_dispatch:

env:
  RUNNER_VERSION: 2.293.0
  ACI_RESOURCE_GROUP: 'Demo-ACI-GitHub-Runners-RG'
  ACI_NAME: 'gh-runner-linux-01'
  DNS_NAME_LABEL: 'gh-lin-01'
  GH_OWNER: 'Pwd9000-ML'
  GH_REPOSITORY: 'docker-github-runner-linux' #Change here to deploy self hosted runner ACI to another repo.

jobs:
  deploy-gh-runner-aci:
    runs-on: ubuntu-latest
    steps:
      # checkout the repo
      - name: 'Checkout GitHub Action'
        uses: actions/checkout@main

      - name: 'Login via Azure CLI'
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      - name: 'Deploy to Azure Container Instances'
        uses: 'azure/aci-deploy@v1'
        with:
          resource-group: ${{ env.ACI_RESOURCE_GROUP }}
          image: ${{ secrets.REGISTRY_LOGIN_SERVER }}/pwd9000-github-runner-lin:${{ env.RUNNER_VERSION }}
          registry-login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
          registry-username: ${{ secrets.REGISTRY_USERNAME }}
          registry-password: ${{ secrets.REGISTRY_PASSWORD }}
          name: ${{ env.ACI_NAME }}
          dns-name-label: ${{ env.DNS_NAME_LABEL }}
          environment-variables: GH_TOKEN=${{ secrets.PAT_TOKEN }} GH_OWNER=${{ env.GH_OWNER }} GH_REPOSITORY=${{ env.GH_REPOSITORY }}
          location: 'uksouth'


Enter fullscreen mode Exit fullscreen mode

The workflow above mainly uses the 'azure/aci-deploy@v1' GitHub Action. You can also set parameters such as 'cpu: 1' and 'memory: 0.1' to spec out the container instance. Check out the documentation of this extension here: ACI deploy GitHub Action.

NOTE: I have added the custom PAT token as a GitHub Secret on the repository: 'GH_TOKEN=${{ secrets.PAT_TOKEN }}':

image.png

We can manually trigger and run the workflow:

image.png

After the workflow has run you should see the self hosted GitHub runner against the repository you specified in the workflow environment variables:

image.png

You will also be able to see the ACI created under the resource group we created earlier:

image.png

To stop and remove the ACI container you can run the following Azure-CLI command:



az container delete --resource-group $aciResourceGroupName --name $aciName


Enter fullscreen mode Exit fullscreen mode

We have successfully deployed self hosted GitHub runners using Azure Container Instances. In the next part of this series we will look at how we can run and automatically scale our self hosted GitHub runners up and down based on load/demand, using Azure Container Apps (ACA) utilizing Kubernetes Event-driven Autoscaling (KEDA).

I hope you have enjoyed this post and have learned something new. You can find the code samples used in this blog post on my GitHub project: docker-github-runner-windows or docker-github-runner-linux. ❤️

Author

Like, share, follow me on: 🐙 GitHub | 🐧 X/Twitter | 👾 LinkedIn

💖 💪 🙅 🚩
pwd9000
Marcel.L

Posted on June 17, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related