I maintain a few container images and stored them in ECR. I use the images mostly to build my blogs (including this one), some tests with different container engines and compiling my programs. Since the task of copying the images from the public registry to my private ECR is pretty much the same every time, I’ve decided to automate it.

Solution #1. Scripting

The first solution consist of a bash script that uses aws cli and skopeo tools, this has the advantage of being really customizable and can be used everywhere, as long as those tools are installed.

#! /usr/bin/env bash

usage() {
    echo "Read image list from file, use: "
    echo "$0 -a IMAGES_FILE,SOURCE_REGISTRY,AWS_ACCOUNT"
    echo "$0 -a images.txt,docker.io,123456789012"
    echo "Read from environment variables, set variables IMAGE and TAG: "
    echo "$0 -e"
    exit 1;
}

login_ecr() {
    AWS_ACCOUNT=${1}
    echo "Login into ECR and making docker credentials"
    aws ecr get-login-password --region us-east-1 | skopeo login --username AWS --password-stdin ${AWS_ACCOUNT}.dkr.ecr.us-east-1.amazonaws.com    
}

copy_images_env() { 
    echo "Reading environment variables!"
    echo "if TAG is not set, latest will be used"
    if [[ -z "${AWS_ACCOUNT}" || -z "${SOURCE_REGISTRY}" || -z "${IMAGE}" ]]; then
        echo "Can't find environment variables"
    else
        login_ecr ${AWS_ACCOUNT}    
        if [[ -z "${TAG}" ]]; then
            TAG="latest"
            skopeo copy docker://${SOURCE_REGISTRY}/${IMAGE}:${TAG} docker://${AWS_ACCOUNT}.dkr.ecr.us-east-1.amazonaws.com/${IMAGE}:${TAG} --all
        else 
            skopeo copy docker://${SOURCE_REGISTRY}/${IMAGE}:${TAG} docker://${AWS_ACCOUNT}.dkr.ecr.us-east-1.amazonaws.com/${IMAGE}:${TAG} --all 
        fi
    fi 
}

copy_images_file() {
    IFS=","
    read -a ARG_ARR <<< ${1}
    IMAGES_FILE=${ARG_ARR[0]}
    REGISTRY=${ARG_ARR[1]}
    AWS_ACCOUNT=${ARG_ARR[2]}
    login_ecr ${AWS_ACCOUNT}
    while read IMAGE TAG; do
        echo "Copying $IMAGE with $TAG"
        skopeo copy docker://${REGISTRY}/${IMAGE}:${TAG} docker://${AWS_ACCOUNT}.dkr.ecr.us-east-1.amazonaws.com/${IMAGE}:${TAG} --all
    done < ${IMAGES_FILE}
    echo "Done"
}

while getopts ":a:e" OPTION; do
    case "${OPTION}" in
        a) 
           copy_images_file ${OPTARG}
           ;;
        e)
           copy_images_env
           ;;
        *)
           usage
           ;;
    esac
done

The script takes several arguments, an image file, containing the image name and the desired tag, comma separated, the source registry and the AWS account ID. It can also read environment variables. While this solution works fine, the main problem is the destination registry, the registry need to be created in advanced with the console or CLI.

Solution #2. Terraform

I recently learned there is a terraform provider for skopeo, with the two providers aws and skopeo, I wrote terraform files that works pretty much the same as the previous script, but it can create the registries with aws_ecr_repository resource.

 resource "aws_ecr_repository" "this" {
 for_each = toset(var.image_name)
 name                 = each.key
 image_tag_mutability = "IMMUTABLE"

 image_scanning_configuration {
   scan_on_push = true
 }
}

resource "skopeo_copy" "this" {
   depends_on = [
     aws_ecr_repository.this
   ]
   for_each = toset(var.image_name)
   source_image        = "docker://${var.source_registry}/${each.key}"  
   destination_image   = "docker://${aws_ecr_repository.this[each.key].repository_url}"
   keep_image          = true
}

Comparison between the two solutions.

terraform scripting
create registry *
custom source registry * *
multiple tags only latest *
read images from file * *
read env variables *

Both solutions can be found on my github:

https://github.com/mental12345/ecr_skopeo