# How to run Azure DevOps self-hosted agents on Azure Container Instances (ACI)

> Learn how to build and deploy self-hosted Azure DevOps build agents using Azure Container Instances (ACI) and Azure Container Registry (ACR).

- Canonical URL: <https://carlossura.com/blog/azure-selfhosted-runner-aci/>
- Author: Carlos Sura
- Published: 2026-08-05
- Tags: azure, aci, azure-devops, azure-pipelines, docker, windows-containers, self-hosted-agent

When configuring custom build environments for **Azure DevOps Pipelines**, running full Virtual Machines (VMs) for self-hosted agents can introduce unnecessary infrastructure maintenance and costs. Instead of provisioning and maintaining full VMs, you can deploy self-hosted pipelines agents on **Azure Container Instances (ACI)** backed by **Azure Container Registry (ACR)**.

Using ACI allows you to rapidly spin up Windows or Linux containerized agents, assign public or private IPs, execute build jobs in isolated environments, and tear them down on demand.

---

## Prerequisites

Before starting, ensure you have:

- An active **Azure Subscription**.
- An **Azure Container Registry (ACR)** instance.
- **Azure CLI** installed and authenticated (**az login**).
- Docker installed (configured for Windows containers if deploying Windows core images).
- An **Azure DevOps Organization** (`https://dev.azure.com/<your-organization>`).
- An **Azure DevOps Personal Access Token (PAT)** with **Agent Pools (Read & Manage)** permissions.
- An existing Agent Pool in Azure DevOps (e.g., **Default** or a custom pool).

---

## Create the Dockerfile

Below is a Windows Server Core **Dockerfile** configured to download and extract the official Azure DevOps pipelines agent package.

```
FROM mcr.microsoft.com/windows/servercore:ltsc2022

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ARG AGENT_VERSION="3.X"
WORKDIR C:/azp

RUN Invoke-WebRequest -Uri "https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-win-x64-${AGENT_VERSION}.zip" -OutFile agent.zip; \
    Expand-Archive -Path agent.zip -DestinationPath . ; \
    Remove-Item agent.zip

COPY start.ps1 C:/azp/start.ps1

ENTRYPOINT ["powershell", "-File", "C:/azp/start.ps1"]
```

---

## Create the Startup Script (**start.ps1**)

The entrypoint PowerShell script configures the agent against your Azure DevOps organization and agent pool, using environment variables passed during container creation, then launches the agent runner.

```
$ErrorActionPreference = "Stop"

if (-not $env:AZP_URL) {
    Write-Error "AZP_URL environment variable is missing."
    exit 1
}

if (-not $env:AZP_TOKEN) {
    Write-Error "AZP_TOKEN environment variable is missing."
    exit 1
}

$agentPool = if ($env:AZP_POOL) { $env:AZP_POOL } else { "Default" }
$agentName = if ($env:AZP_AGENT_NAME) { $env:AZP_AGENT_NAME } else { "aci-agent-$(hostname)" }

Set-Location C:\azp

# Configure the Azure DevOps Pipelines agent
.\config.cmd --unattended `
  --url "$env:AZP_URL" `
  --auth PAT `
  --token "$env:AZP_TOKEN" `
  --pool "$agentPool" `
  --agent "$agentName" `
  --replace `
  --acceptTeeEula

# Run the agent worker process
.\run.cmd
```

> **Tip**: If you want the container to execute a single job and exit, you can append **--once** to **.\config.cmd**.

---

## Build and Push Image to Azure Container Registry (ACR)

Authenticate to your ACR instance, tag your built agent image, and push it:

```
# Login to ACR
az acr login --name <your-acr-name>

# Tag local image
docker tag azp-agent-win:latest <your-acr-name>.azurecr.io/azp-agent-win:latest

# Push to ACR
docker push <your-acr-name>.azurecr.io/azp-agent-win:latest
```

---

## Deploy the Agent on Azure Container Instances (ACI)

Deploy your agent container to Azure using **az container create**. Using **--secure-environment-variables** ensures sensitive credentials such as your PAT token are protected and hidden in Azure Resource Manager logs.

```
az container create `
  --resource-group myACIRunnersRG `
  --name azp-runner-win-01 `
  --image <your-acr-name>.azurecr.io/azp-agent-win:latest `
  --registry-login-server <your-acr-name>.azurecr.io `
  --registry-username <acr-username> `
  --registry-password <acr-password> `
  --os-type Windows `
  --cpu 2 --memory 4 `
  --environment-variables AZP_URL=https://dev.azure.com/<your-organization> AZP_POOL=Default AZP_AGENT_NAME=aci-win-agent-01 `
  --secure-environment-variables AZP_TOKEN=<your-azure-devops-pat> `
  --ip-address Public `
  --restart-policy Never `
  --location <location>
```

Running Azure DevOps self-hosted agents on Azure Container Instances gives you a lightweight, cost-effective, and fully isolated environment for build and deployment tasks without the overhead of maintaining persistent Virtual Machines.

---

## References

- [Run a self-hosted agent in Docker](https://learn.microsoft.com/en-us/azure/devops/pipelines/agents/docker)
- [Deploy a container instance in Azure using the Azure CLI](https://learn.microsoft.com/en-us/azure/container-instances/container-instances-quickstart)
- [Set environment variables in Azure Container Instances](https://learn.microsoft.com/en-us/azure/container-instances/container-instances-environment-variables)
- [Azure Container Registry Documentation](https://learn.microsoft.com/en-us/azure/container-registry/)
