<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tuan Saad</title>
    <description>The latest articles on DEV Community by Tuan Saad (@tuan_saad_bd99b8fecac2e88).</description>
    <link>https://dev.to/tuan_saad_bd99b8fecac2e88</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2637443%2F8d13b04a-fd4d-495a-a195-c275205f8a06.jpg</url>
      <title>DEV Community: Tuan Saad</title>
      <link>https://dev.to/tuan_saad_bd99b8fecac2e88</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tuan_saad_bd99b8fecac2e88"/>
    <language>en</language>
    <item>
      <title>How to Configure Container App jobs as GitHub Action runners</title>
      <dc:creator>Tuan Saad</dc:creator>
      <pubDate>Fri, 15 Aug 2025 22:04:24 +0000</pubDate>
      <link>https://dev.to/tuan_saad_bd99b8fecac2e88/how-to-configure-container-app-jobs-as-github-runners-2m29</link>
      <guid>https://dev.to/tuan_saad_bd99b8fecac2e88/how-to-configure-container-app-jobs-as-github-runners-2m29</guid>
      <description>&lt;h1&gt;
  
  
  Azure Container Apps GitHub Actions Runner Setup Guide
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Tired of paying for CI/CD runners that sit idle? Azure Container Apps jobs automatically spin up GitHub runners only when your workflows run, then shut them down when finished. You only pay for actual usage while keeping pipelines secure in private networks—no more expensive always-on VMs eating your budget&lt;/p&gt;

&lt;p&gt;This guide will help you set up a GitHub Actions self-hosted runner using Azure Container Apps. The runner will automatically scale based on your GitHub workflow queue and execute your CI/CD pipelines in isolated containers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure CLI installed and configured&lt;/li&gt;
&lt;li&gt;An active Azure subscription&lt;/li&gt;
&lt;li&gt;A GitHub repository with Actions enabled&lt;/li&gt;
&lt;li&gt;GitHub Personal Access Token (PAT) with appropriate permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Required Permissions for GitHub PAT
&lt;/h2&gt;

&lt;p&gt;Your GitHub Personal Access Token needs the following scopes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;repo&lt;/code&gt; (Full control of private repositories)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;workflow&lt;/code&gt; (Update GitHub Action workflows)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;admin:org&lt;/code&gt; (if using organization-level runners)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Install Azure Container Apps Extension
&lt;/h2&gt;

&lt;p&gt;First, add the Container Apps extension to Azure CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az extension add &lt;span class="nt"&gt;--name&lt;/span&gt; containerapp &lt;span class="nt"&gt;--upgrade&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Configure Environment Variables
&lt;/h2&gt;

&lt;p&gt;Set up your configuration variables. Replace the placeholder values with your actual information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Resource configuration&lt;/span&gt;
&lt;span class="nv"&gt;RESOURCE_GROUP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"jobs-sample"&lt;/span&gt;
&lt;span class="nv"&gt;LOCATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"northcentralus"&lt;/span&gt;
&lt;span class="nv"&gt;ENVIRONMENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"env-jobs-sample"&lt;/span&gt;
&lt;span class="nv"&gt;JOB_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"github-actions-runner-job"&lt;/span&gt;

&lt;span class="c"&gt;# GitHub configuration&lt;/span&gt;
&lt;span class="nv"&gt;GITHUB_PAT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_github_personal_access_token_here"&lt;/span&gt;
&lt;span class="nv"&gt;REPO_OWNER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-github-username"&lt;/span&gt;
&lt;span class="nv"&gt;REPO_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-repository-name"&lt;/span&gt;

&lt;span class="c"&gt;# Container configuration&lt;/span&gt;
&lt;span class="nv"&gt;CONTAINER_IMAGE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"github-actions-runner:1.0"&lt;/span&gt;
&lt;span class="nv"&gt;CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-unique-registry-name"&lt;/span&gt;

&lt;span class="c"&gt;# Identity configuration&lt;/span&gt;
&lt;span class="nv"&gt;IDENTITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"github-actions-runner-identity"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ &lt;strong&gt;Security Note&lt;/strong&gt;: Never commit your GitHub PAT to version control. Consider using Azure Key Vault for production environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Create Azure Container Registry
&lt;/h2&gt;

&lt;p&gt;Create a container registry to store your runner image.&lt;br&gt;
I've installed all the required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az acr create &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCATION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--sku&lt;/span&gt; Basic

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Configure Registry Authentication
&lt;/h2&gt;

&lt;p&gt;Enable authentication-as-ARM for your container registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az acr config authentication-as-arm show &lt;span class="nt"&gt;--registry&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Build the Runner Container Image
&lt;/h2&gt;

&lt;p&gt;Build your GitHub Actions runner container image from the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az acr build &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--registry&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--image&lt;/span&gt; github-actions-runner:2.1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--file&lt;/span&gt; &lt;span class="s2"&gt;"Dockerfile.github"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"https://github.com/TuanLikeminds/container-apps-ci-cd-runner-tutorial.git"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've customized the Dockerfile used to build the github-actions running container image that can be found at &lt;a href="https://github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial/blob/main/Dockerfile.github" rel="noopener noreferrer"&gt;https://github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial/blob/main/Dockerfile.github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pre-installed the Azure-CLI, Kubectl, and Helm binaries required by the actions runner docker container by installing Azure CLI and Kubectl. See below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;FROM ghcr.io/actions/actions-runner:2.304.0
&lt;span class="c"&gt;# for latest release, see https://github.com/actions/runner/releases&lt;/span&gt;

USER root

&lt;span class="c"&gt;# install curl and jq&lt;/span&gt;



RUN apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl jq apt-transport-https ca-certificates gnupg lsb-release git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    apt-get clean &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;# install Azure CLI&lt;/span&gt;
&lt;span class="c"&gt;# https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?view=azure-cli-latest&amp;amp;pivots=apt#option-1-install-with-one-command&lt;/span&gt;
RUN curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://aka.ms/InstallAzureCLIDeb | bash &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
RUN az aks install-cli

RUN  curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://storage.googleapis.com/kubernetes-release/release/&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://storage.googleapis.com/kubernetes-release/release/stable.txt&lt;span class="si"&gt;)&lt;/span&gt;/bin/linux/amd64/kubectl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./kubectl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;mv&lt;/span&gt; ./kubectl /usr/local/bin/kubectl


COPY github-actions-runner/entrypoint.sh ./entrypoint.sh
RUN &lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./entrypoint.sh

USER runner

ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./entrypoint.sh"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Create the Container App Job
&lt;/h2&gt;

&lt;p&gt;Create the container app job with auto-scaling configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az containerapp job create &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JOB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--environment&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ENVIRONMENT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--trigger-type&lt;/span&gt; Event &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--replica-timeout&lt;/span&gt; 1800 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--replica-retry-limit&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--replica-completion-count&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--parallelism&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--image&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="s2"&gt;.azurecr.io/&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_IMAGE_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--min-executions&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--max-executions&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--polling-interval&lt;/span&gt; 30 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scale-rule-name&lt;/span&gt; &lt;span class="s2"&gt;"github-runner"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scale-rule-type&lt;/span&gt; &lt;span class="s2"&gt;"github-runner"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scale-rule-metadata&lt;/span&gt; &lt;span class="s2"&gt;"githubAPIURL=https://api.github.com"&lt;/span&gt; &lt;span class="s2"&gt;"owner=&lt;/span&gt;&lt;span class="nv"&gt;$REPO_OWNER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"runnerScope=repo"&lt;/span&gt; &lt;span class="s2"&gt;"repos=&lt;/span&gt;&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"targetWorkflowQueueLength=1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scale-rule-auth&lt;/span&gt; &lt;span class="s2"&gt;"personalAccessToken=personal-access-token"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cpu&lt;/span&gt; &lt;span class="s2"&gt;"2.0"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--memory&lt;/span&gt; &lt;span class="s2"&gt;"4Gi"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secrets&lt;/span&gt; &lt;span class="s2"&gt;"personal-access-token=&lt;/span&gt;&lt;span class="nv"&gt;$GITHUB_PAT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--env-vars&lt;/span&gt; &lt;span class="s2"&gt;"GITHUB_PAT=secretref:personal-access-token"&lt;/span&gt; &lt;span class="s2"&gt;"GH_URL=https://github.com/&lt;/span&gt;&lt;span class="nv"&gt;$REPO_OWNER&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--registry-server&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="s2"&gt;.azurecr.io"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--mi-user-assigned&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IDENTITY_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--registry-identity&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IDENTITY_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Configuration Parameters Explained
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;replica-timeout&lt;/strong&gt;: Maximum time (30 minutes) a job can run&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;min-executions/max-executions&lt;/strong&gt;: Scaling limits (0-10 concurrent runners)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;polling-interval&lt;/strong&gt;: How often to check for new workflows (30 seconds)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;targetWorkflowQueueLength&lt;/strong&gt;: Triggers scaling when queue length reaches 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cpu/memory&lt;/strong&gt;: Resource allocation per runner instance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 7: Configure Role Assignments
&lt;/h2&gt;

&lt;p&gt;Set up the necessary permissions for your identities. You'll need to replace the GUIDs with your actual identity IDs:&lt;/p&gt;

&lt;h3&gt;
  
  
  For Container Registry Access
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Replace with your managed identity ID&lt;/span&gt;
&lt;span class="nv"&gt;IDENTITY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-managed-identity-id"&lt;/span&gt;

&lt;span class="c"&gt;# ACR Pull permissions&lt;/span&gt;
az role assignment create &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--assignee&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IDENTITY_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt; AcrPull &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scope&lt;/span&gt; &lt;span class="s2"&gt;"/subscriptions/your-subscription-id/resourceGroups/&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;/providers/Microsoft.ContainerRegistry/registries/&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# ACR Push permissions (if needed for building images)&lt;/span&gt;
az role assignment create &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--assignee&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IDENTITY_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt; AcrPush &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scope&lt;/span&gt; &lt;span class="s2"&gt;"/subscriptions/your-subscription-id/resourceGroups/&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;/providers/Microsoft.ContainerRegistry/registries/&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_REGISTRY_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For AKS Access (if deploying to Kubernetes)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az role assignment create &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--assignee&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IDENTITY_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt; &lt;span class="s2"&gt;"Azure Kubernetes Service RBAC Admin"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scope&lt;/span&gt; &lt;span class="s2"&gt;"/subscriptions/your-subscription-id/resourceGroups/your-aks-resource-group/providers/Microsoft.ContainerService/managedClusters/your-aks-cluster-name"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8: Verify Setup
&lt;/h2&gt;

&lt;p&gt;After completing the setup, verify your configuration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check Container App Job Status&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az containerapp job show &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JOB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitor Logs&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az containerapp job logs show &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JOB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: Check your repository's Actions tab for the new self-hosted runner.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trigger&lt;/strong&gt;: When a workflow is queued in your GitHub repository&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale&lt;/strong&gt;: Container Apps detects the queue and starts a new runner instance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute&lt;/strong&gt;: The runner picks up and executes the workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Up&lt;/strong&gt;: After completion, the runner instance is terminated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale Down&lt;/strong&gt;: When no workflows are queued, the system scales to zero&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common Issues
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Runner Not Appearing in GitHub&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Verify your GitHub PAT has correct permissions&lt;/li&gt;
&lt;li&gt;Check the REPO_OWNER and REPO_NAME variables&lt;/li&gt;
&lt;li&gt;Review container logs for authentication errors&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling Issues&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Ensure polling-interval and scale rule metadata are correctly configured&lt;/li&gt;
&lt;li&gt;Check if targetWorkflowQueueLength matches your needs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Registry Access&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Verify role assignments for your managed identity&lt;/li&gt;
&lt;li&gt;Ensure the container image exists in your registry&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Useful Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# View job executions&lt;/span&gt;
az containerapp job execution list &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JOB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Get detailed logs&lt;/span&gt;
az containerapp job logs show &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JOB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--follow&lt;/span&gt;

&lt;span class="c"&gt;# Update job configuration&lt;/span&gt;
az containerapp job update &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JOB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--image&lt;/span&gt; &lt;span class="s2"&gt;"new-image:tag"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Security Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use Managed Identities&lt;/strong&gt;: Avoid storing credentials in environment variables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least Privilege&lt;/strong&gt;: Grant only necessary permissions to your identities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regular Token Rotation&lt;/strong&gt;: Rotate GitHub PATs regularly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Security&lt;/strong&gt;: Consider using private endpoints for production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Limits&lt;/strong&gt;: Set appropriate CPU and memory limits&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cost Optimization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scale to Zero&lt;/strong&gt;: Runners automatically scale down when not in use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Sizing&lt;/strong&gt;: Adjust CPU/memory based on your workflow requirements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regional Deployment&lt;/strong&gt;: Choose regions close to your development team&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: Use Azure Monitor to track usage and optimize&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Set up monitoring and alerting for your runners&lt;/li&gt;
&lt;li&gt;Configure network policies for enhanced security&lt;/li&gt;
&lt;li&gt;Implement GitOps workflows using your new runners&lt;/li&gt;
&lt;li&gt;Consider setting up multiple runner pools for different workload types&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Remember to replace all placeholder values (subscription IDs, resource names, GitHub information) with your actual configuration before running the commands.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
