Search code examples
amazon-web-servicesdockeramazon-ecr

How to pull every single image (tag or untagged) from AWS ECR?


My target is to copy every single image from each repository from one region and push them into another region. I have the following script that does that, however it only pulls the "latest" images.

#!/bin/bash
TARGET_ACCOUNT_REGION="us-west-2"
DESTINATION_ACCOUNT_REGION="us-west-2"
DESTINATION_ACCOUNT_BASE_PATH="123456.dkr.ecr.$DESTINATION_ACCOUNT_REGION.amazonaws.com/"


REPO_LIST=($(aws ecr describe-repositories --query 'repositories[].repositoryUri' --output text --region $TARGET_ACCOUNT_REGION))
REPO_NAME=($(aws ecr describe-repositories --query 'repositories[].repositoryName' --output text --region $TARGET_ACCOUNT_REGION))


for repo_url in ${!REPO_LIST[@]}; do
        echo "star pulling image ${REPO_LIST[$repo_url]} from Target account"
        docker pull ${REPO_LIST[$repo_url]}


        # Create repo in destination account, remove this line if already created
        aws ecr create-repository --repository-name ${REPO_NAME[$repo_url]}
        docker tag   ${REPO_LIST[$repo_url]} $DESTINATION_ACCOUNT_BASE_PATH/${REPO_NAME[$repo_url]} 
        docker push $DESTINATION_ACCOUNT_BASE_PATH/${REPO_NAME[$repo_url]} 
done

This does not take every image into count. Is there any other way to do so?


Solution

  • Try iterating over tags for each repository:

    #!/bin/bash
    
    set -e  # -e quit on error
    
    ACCOUNT_ID="123456"
    TARGET_ACCOUNT_REGION="us-west-1"
    DESTINATION_ACCOUNT_REGION="us-west-2"
    DESTINATION_ACCOUNT_BASE_PATH="$ACCOUNT_ID.dkr.ecr.$DESTINATION_ACCOUNT_REGION.amazonaws.com/"
    
    REPO_LIST=($(aws ecr describe-repositories --query 'repositories[].repositoryUri' --output text --region $TARGET_ACCOUNT_REGION))
    REPO_NAME=($(aws ecr describe-repositories --query 'repositories[].repositoryName' --output text --region $TARGET_ACCOUNT_REGION))
    
    for repo_url in "${!REPO_LIST[@]}"; do
        # Create repository. Throws an error when a repository exists;
        # could be extracted into a separate function which checks
        # for presence beforehand / ignores the RepositoryAlreadyExistsException
        # We could also remove the -e flag, risking missing errors on other parts of the script
        aws ecr create-repository --repository-name "${REPO_NAME[$repo_url]}" --region $DESTINATION_ACCOUNT_REGION
    
        echo "== Start copying images from ${REPO_LIST[$repo_url]} to ${DESTINATION_ACCOUNT_BASE_PATH}${REPO_NAME[$repo_url]}"
        IMAGE_TAGS=($(aws ecr list-images --repository-name ${REPO_NAME[$repo_url]} --query 'imageIds[].imageTag' --output text --region $TARGET_ACCOUNT_REGION))
        for tag in "${!IMAGE_TAGS[@]}"; do
            IMAGE_SRC="${REPO_LIST[$repo_url]}:${IMAGE_TAGS[$tag]}"
            IMAGE_DEST="$DESTINATION_ACCOUNT_BASE_PATH${REPO_NAME[$repo_url]}:${IMAGE_TAGS[$tag]}"
            echo "-- Copying image $IMAGE_SRC"
            docker pull $IMAGE_SRC
            docker tag $IMAGE_SRC $IMAGE_DEST
            docker push $IMAGE_DEST
        done
    done