I use Azure Container Registry Tasks to build Docker images in a serverless way. Instead of running image builds on my own build agents, I let ACR handle the build and push process for each environment.

My setup uses source triggers. A push to the develop branch causes a Docker image to be built and pushed to the DEV environment’s ACR. A push to main causes a Docker image to be built in the PROD environment’s ACR. Each environment has its own registry, its own ACR task, and its own source trigger watching the appropriate branch.

This setup works extremely well once it is in place because it keeps image builds close to the registry itself. There is no dedicated build server to maintain, no runner pool to scale, and no extra CI infrastructure whose only job is to execute docker build.

One strange limitation is that the Azure Portal UI does not make it easy to manually trigger these tasks. You can inspect tasks in the portal, but actually kicking one off on demand is awkward enough that I eventually stopped looking for the button. The Azure CLI ends up being the real operational interface for ACR Tasks, especially once you start managing multiple services and environments.

Because of that, I keep a few CLI commands close by at all times. I even built a Bash script that rebuilds all of my images when I want to force-push a branch across all services.

Manually Trigger a Task

This is probably the command I use the most. It immediately queues a build using the task definition already stored in ACR.

az acr task run --registry crz1234567 --name svc-foo

This is especially useful when:

  • A source trigger did not fire the way you expected
  • You need to rebuild an image without making a meaningless Git commit
  • You force-pushed or rebased a branch and want a clean rebuild
  • You rotated secrets or package credentials and want to validate builds
  • You are debugging Dockerfile changes and need fast iteration

Since the task already knows the Git repo, branch, Dockerfile path, build arguments, and image naming convention, triggering a rebuild becomes a single command.

In practice, this starts feeling very similar to invoking a lightweight serverless build job.

Show the Task Definition

When something is broken, this command becomes incredibly valuable because it exposes the actual stored task configuration instead of whatever you think the configuration might be.

az acr task show \
  --registry crz1234567 \
  --name svc-foo \
  --output yaml

The YAML output is useful for validating things like:

  • Which Git branch the task is watching
  • Which Dockerfile path is configured
  • Whether push is enabled
  • What image naming convention is being used
  • Which build arguments and secrets are configured
  • Whether the task is enabled
  • What repository URL the task is actually pointing at

I have used this command more than once to discover a task was still watching an old branch or using an outdated Dockerfile path after a refactor.

agentConfiguration: null
agentPoolName: null
creationDate: '<redacted>'
credentials: null
id: /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.ContainerRegistry/registries/<registry>/tasks/<task-name>

identity:
  principalId: null
  tenantId: null
  type: None
  userAssignedIdentities: null

isSystemTask: false
location: <region>

logTemplate: null

name: <task-name>

platform:
  architecture: null
  os: Linux
  variant: null

provisioningState: Succeeded

resourceGroup: <resource-group>

status: Enabled

step:
  arguments:
    - isSecret: false
      name: GITHUB_USER
      value: <github-user>

    - isSecret: false
      name: GITHUB_PACKAGE_SOURCE
      value: <private-package-source>

    - isSecret: true
      name: GITHUB_PAT
      value: null

  baseImageDependencies: null
  contextAccessToken: null

  contextPath: https://github.com/<org>/<repo>#<branch>:<path>

  dockerFilePath: <dockerfile-path>

  imageNames:
    - <image-name>:

  isPushEnabled: true
  noCache: false
  target: null
  type: Docker

systemData:
  createdAt: '<redacted>'
  createdBy: <redacted>
  createdByType: Application
  lastModifiedAt: '<redacted>'
  lastModifiedBy: <redacted>
  lastModifiedByType: Application

tags:
  application: <application-name>
  audit_exempt: 'false'
  description: <redacted-description>
  environment: <environment>
  owner: <redacted-email>
  phi: 'false'
  user_data: 'false'

timeout: 3600

trigger:
  baseImageTrigger: null

  sourceTriggers:
    - name: <branch-name>

      sourceRepository:
        branch: <branch>
        repositoryUrl: https://github.com/<org>/<repo>
        sourceControlAuthProperties: null
        sourceControlType: Github

      sourceTriggerEvents:
        - commit

      status: Enabled

  timerTriggers: null

type: Microsoft.ContainerRegistry/registries/tasks

Conclusion

ACR Tasks are a clean way to build Docker images without managing build infrastructure and they pair nicely with another serverless container service: Azure Container Apps.

Source triggers make the normal workflow automatic: develop builds DEV images, and main builds PROD images. Once the tasks are configured correctly, the Azure CLI becomes the primary operational surface for rebuilding images, validating task definitions, and debugging trigger behavior.

The portal may expose the configuration, but the CLI is what actually makes the system pleasant to operate day to day. Hope this helps!