Created
July 4, 2024 16:28
-
-
Save zxkane/4624d699ff664698d94e3b8bf51de3e2 to your computer and use it in GitHub Desktop.
Revisions
-
zxkane created this gist
Jul 4, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,112 @@ #!/bin/bash set -o errexit # exit on first error set -o nounset # exit on using unset variables set -o pipefail # exit on any error in a pipeline set -x # enable debugging # Script to mirror multi-arch images from Docker Hub to Amazon ECR Public. # Usage: ./mirror-multi-arch-repos.sh <source-image>:<tag> <ecr-repo-name> if [ $# -ne 2 ]; then echo "Usage: $0 <source-image>:<tag> <ecr-repo-name>" exit 1 fi SOURCE_IMAGE_TAG_STR=$1 ECR_REPO_NAME=$2 # Get ECR registry URL ECR_REGISTRY_URL=$(aws ecr-public describe-registries --region us-east-1 --query 'registries[0].registryUri' --output text) # Function to extract platform from manifest as a list of json strings get_platforms() { docker manifest inspect $SOURCE_IMAGE_TAG_STR | jq -r '.manifests[].platform | select(.architecture!="unknown") | @json' } get_suffix() { local os=$1 local arch=$2 local variant=${3:-""} prefix="-" suffix=${os}-${arch}${variant:+$prefix$variant} echo $suffix } # Pull and push images to ECR pull_and_push_to_ecr() { # Create ECR repository if it doesn't exist aws ecr-public create-repository --repository-name $ECR_REPO_NAME --region us-east-1 || true platforms=( $(get_platforms) ) for platform in "${platforms[@]}"; do arch=$(echo $platform | jq -r .architecture) os=$(echo $platform | jq -r .os) variant=$(echo $platform | jq -r '.variant? // empty') suffix=$(get_suffix $os $arch $variant) local source_image_with_platform="${SOURCE_IMAGE_TAG_STR}-${suffix}" local ecr_image_with_arch="${ECR_REGISTRY_URL}/${source_image_with_platform}" echo "Pulling $SOURCE_IMAGE_TAG_STR for $suffix" docker pull --platform $os/$arch${variant:+/$variant} $SOURCE_IMAGE_TAG_STR echo "Tagging $SOURCE_IMAGE_TAG_STR as $ecr_image_with_arch" docker tag $SOURCE_IMAGE_TAG_STR $ecr_image_with_arch echo "Pushing $ecr_image_with_arch to ECR" docker push $ecr_image_with_arch done } # Create and push manifest list create_manifest() { local manifest_list="${ECR_REGISTRY_URL}/${SOURCE_IMAGE_TAG_STR}" echo "Creating manifest list: $manifest_list" platforms=( $(get_platforms) ) for platform in "${platforms[@]}"; do arch=$(echo $platform | jq -r .architecture) os=$(echo $platform | jq -r .os) variant=$(echo $platform | jq -r '.variant? // empty') suffix=$(get_suffix $os $arch $variant) # Construct the image tag with the suffix image_tag="${SOURCE_IMAGE_TAG}-${suffix}" # Add the image to the manifest list docker manifest create "$manifest_list" "${ECR_REGISTRY_URL}/${SOURCE_IMAGE}:${image_tag}" --amend docker manifest annotate $manifest_list \ "${ECR_REGISTRY_URL}/${SOURCE_IMAGE}:${image_tag}" \ --os $os --arch $arch ${variant:+--variant $variant} done echo "Pushing manifest list to ECR" docker manifest push $manifest_list } # a method to parse the image name and tag from SOURCE_IMAGE_TAG_STR # e.g. "nginx:latest" will be split into "nginx" and "latest" SOURCE_IMAGE=$(echo $SOURCE_IMAGE_TAG_STR | cut -d: -f1) SOURCE_IMAGE_TAG=$(echo $SOURCE_IMAGE_TAG_STR | cut -d: -f2) # Main execution echo "Authenticating with ECR" aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws echo "Pulling multi-architecture images for $SOURCE_IMAGE_TAG_STR, then pushing images to ECR" pull_and_push_to_ecr echo "Creating and pushing manifest list" create_manifest echo "Mirroring complete for $SOURCE_IMAGE_TAG_STR to ${ECR_REGISTRY_URL}/${ECR_REPO_NAME}"