7

I have a private Docker repository on AWS ECR.

I'm trying to tag an existing image with a new tag using the instructions here https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-retag.html

For example, say I have an image with tag "1.5.0", and now I want to add the tag "lts", by using the method above to "batch-get-image" of tag "1.5.0", and then "put-image" with "image-tag" "lts", the command creates a brand new image in the repository with the tag "lts". The original image "1.5.0" is unaffected.

Code:

MANIFEST=$(aws ecr batch-get-image --region eu-west-1 --repository-name mynamespace/repo --image-ids imageTag='1.5.0' --query 'images[].imageManifest' --output text)
aws ecr put-image --region eu-west-1 --repository-name mynamespace/repo --image-tag lts --image-manifest "$MANIFEST"

The above results in two separate images:

  • lts
  • 1.5.0

I want 1 image:

  • 1.5.0, lts

Any ideas what I'm doing wrong? The repository setting has immutability disabled.

I would rather avoid the docker pull, docker tag, docker push approach as this will run on my CI server (Github Actions) in a separate workflow where docker pull would be a very wasteful command.

Omair Vaiyani
  • 398
  • 3
  • 12

1 Answers1

2

The issue is whitespace in the manifest.

--output text is going to introduce whitespace that won't produce the same sha as the original, thus it will post a new image.

So you want to use jq as so:

MANIFEST=$(aws ecr batch-get-image --repository-name amazonlinux --image-ids imageTag=latest --output json | jq --raw-output '.images[].imageManifest')

(as described here) How do I re-tag an image in ECR?

You will have to manage the whitespace no matter what language you're dealing with. For me, to manage this in ruby, what worked for me was to parse it as json.

Also, one thing I learned is that you can protect yourself from inadvertently creating a new image by specifying the sha that you are expecting. In this code below, I

  • look up the image by tag and grab the imageDigest sha,
  • use that sha to get the manifest
  • pass the digest sha and the manifest to the put-image command

Amazon will return an error if its sha of the manifest doesn't match the digest sha you gave it, thus allowing the command to fail rather than create the additional image you didn't want.

digest = `aws ecr batch-get-image --repository-name #{name} --image-ids=imageTag=#{tag} --output json | jq --raw-output '.images[0].imageId.imageDigest'`.strip

pre_manifest = `aws ecr batch-get-image --repository-name #{name} --image-ids=imageDigest=#{digest} --output json | jq '.images[0].imageManifest'`

manifest = JSON.parse(pre_manifest)

# run_command is a wrapper around a system call

run_command("aws ecr put-image --repository-name #{name} --image-tag latest --image-digest #{digest} --image-manifest '#{manifest}'")