Comparing local and remote image built in Docker

1.7k Views Asked by At

I am trying to write a script for simple tagging docker images based on the contents of Dockerfile, basically something like "auto-versioning".

The current process is:

  1. Check the latest version in Docker repository (I am using AWS ECR)
  2. Get the digest for that image
  3. Build image from Dockerfile locally
  4. Compare digests from the remote image and local image

Now here is the problem. The locally built image doesn't have the RepoDigest that I want to compare against, because it wasn't in the repository yet.

Here's the error:

Template parsing error: template: :1:2: executing "" at <index .RepoDigests 0>: error calling index: index out of range: 0

The other approach I could think of is pulling the remote image, building the local one and comparing layers, if the layers are identical, no action, if they are different = new version and I can issue a new tag and push the image. I am not so sure if the layers are reliable for this manner.

Another possible approach would be building the image with some temporary tag e.g. pointer, pushing anyways and in case the tag is identical with the latest version, not issuing a new version and stopping there. That would mean there would always be pointer tag somewhere in the repository. (I am also thinking that this could be a definiton of the latest tag?)

This is the script that I am using for building the images:

#!/usr/bin/env bash

repository=myrepo
path=mypath.dkr.ecr.ohio-1.amazonaws.com/${repository}/

set -e
set -o pipefail

if [[ $# -gt 0 ]]; then
    if [[ -d "$1" ]]; then
        latest=$(aws ecr describe-images --repository-name ${repository}/$1 --output text --query 'sort_by(imageDetails,& imagePushedAt)[*].imageTags[*]' | tr '\t' '\n' | grep -e '^[0-9]$' | tail -1 )  || true
        if [[ -z "$latest" ]]; then
            latest=0
        fi
    else
        echo "$1 is not a directory"
        exit 1
    fi
else
   echo "Provide build directory"
   exit 1
fi

image="$path$1"
temporaryImage="$image:build"

echo "Building $image..."
docker build -t ${temporaryImage} $1

if [[ ${latest} -gt 0 ]]; then
    latestDigest=$(aws ecr describe-images --repository-name ${repository}/$1 --image-ids "imageTag=${latest}" | jq -r '.imageDetails[0].imageDigest')
    buildDigest=$(docker inspect --format='{{index .RepoDigests 0}}' ${temporaryImage})
    if [[ "$image@$latestDigest" == "$buildDigest" ]]; then
        echo "The desired version of the image is already present in the remote repository"
        exit 1
    fi
    version=$((latest+1))
else
    version=1
fi

versionedImage="$image:$version"
latestImage="$image:latest"
devImage="$image:dev"
devVersion="$image:$version-dev"

docker tag ${temporaryImage} ${versionedImage}
docker tag ${versionedImage} ${latestImage}
docker push ${versionedImage}
docker push ${latestImage}
echo "Image '$versionedImage' pushed successfully!"

docker build -t ${devImage} $1/dev/
docker tag ${devImage} ${devVersion}
docker push ${devImage}
docker push ${devVersion}
echo "Development image '$devImage' pushed successfully!"
0

There are 0 best solutions below