Azure DevOps yaml: push docker image to different ACRs

Viewed 264

I need to build a docker image in Azure pipeline and push it to different ACRs. I can successfully push an image to the same ACR where it was buid, but when pushing to other ACR the push task fails with "An image does not exist locally with the tag" error.

- task: Docker@2
  displayName: Build
  inputs:
    command: build
    containerRegistry: REGISTRY1
    repository: $(ACR_URL1)/test
    tags: |
      latest

# This push succeeds
- task: Docker@2
  displayName: Push to ACR1
  inputs:
    command: push
    containerRegistry: REGISTRY1
    repository: $(ACR_URL1)/test
    tags: |
      latest

# This push fails
- task: Docker@2
  displayName: Push to ACR2
  inputs:
    command: push
    containerRegistry: REGISTRY2
    repository: $(ACR_URL2)/test
    tags: |
      latest

The obvious workaround is to separately build an image on each ACR, but it is far from optimal since the build takes almost an hour. And unfortunately, I cannot use docker command line, only DevOps tasks (like Docker@2).

2 Answers

The solution happened to be very simple (yet far from obvious). Login to all the ACRs you want to push your image to and do not specify the containerRegistry property in the push task - it will push the image to all the ACRs you logged in. Example:

- task: Docker@2
  inputs:
    command: login
    containerRegistry: DEV-ACR

- task: Docker@2
  inputs:
    command: login
    containerRegistry: TST-ACR

- task: Docker@2
  displayName: Push to both DEV-ACR and TST-ACR. Note: containerRegistry property is missing!
  inputs:
    command: buildAndPush
    repository: test

You have to tag the container properly.

Let's say you have two ACRs: foo.azurecr.io and bar.azurecr.io

Your first step builds the container and tags it as foo.azurecr.io/test:latest. You can push that to foo.azurecr.io because it's tagged appropriately.

The second push fails because the container isn't tagged as bar.azurecr.io/test:latest. You need to tag it. Given your restriction that you can't just run docker tag from the command line, you can have a second build task. It will only take a few seconds to run because the container is already built.

i.e.

- task: Docker@2
  displayName: Build
  inputs:
    command: build
    containerRegistry: REGISTRY1
    repository: $(ACR_URL1)/test
    tags: |
      latest

- task: Docker@2
  displayName: Build
  inputs:
    command: build
    containerRegistry: REGISTRY2
    repository: $(ACR_URL2)/test
    tags: |
      latest
Related