Create an elastic container registry repo with CloudFormation

What is Amazon ECR?

A Container Registry is a centralized way to distribute and manage container images. Amazon ECR is simply a container registry that AWS provides, and we can create public and private images, just like on Docker Hub.

Why use Amazon ECR?

Ecosystem

Some teams prefer to keep all their services in the same ecosystem. In this case, AWS can make things much easier to manage and control user access. For example, we can use ECR instead of Docker Hub or Amazon Elastic Container Service (a fully managed container orchestration service) instead of Kubernetes (the de-facto standard for container orchestration). Instead, we can use Kubernetes on AWS with Amazon Elastic Kubernetes Service.

Rate limits

There is at least one other reason to use ECR. If our team uses free Docker Hub, we might run into rate limits while pulling images into something like AWS CodeBuild. The rate limit is set to 100 pulls per 6 hours per IP address if we are anonymous and 200 pulls per 6 hours for authenticated users with a Docker ID.

Example of Docker Hub CodeBuild rate limit error

CannotPullContainerError: inspect image has been retried 5 time(s): httpReaderSeeker: failed open: unexpected status code https://registry-1.docker.io/v2/manifests/sha256:2bb501e6429 Too Many Requests - Server message: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit

The cheapest way to overcome this might be to add the image to our AWS accounts ECR and use that instead.

Create the ECR repository

We can create an ECR repository manually in the ECR console, but we will focus on the CloudFormation method.

We can create a file called ecr.yml and paste the template below:

AWSTemplateFormatVersion: "2010-09-09"

Description: >
  This template creates ECR resources

Parameters:
  IAMUserName:
    Type: String
    Description: IAM User Name
    Default: "YOUR_USER_NAME"
    AllowedPattern: "[a-zA-Z0-9-_]+"
    ConstraintDescription: must be a valid IAM user name  

Resources:
  ECRRepository:
    Type: AWS::ECR::Repository
    Properties:
      RepositoryName: !Ref AWS::StackName
      RepositoryPolicyText:
        Version: "2012-10-17"
        Statement:
          - Sid: "AllowPushPull"
            Effect: Allow
            Principal:
              AWS:
                !Join [
                  "",
                  [
                    "arn:aws:iam::",
                    !Ref AWS::AccountId,
                    ":user/",
                    !Ref IAMUserName
                  ],
                ]
            Action:
              - "ecr:GetDownloadUrlForLayer"
              - "ecr:BatchGetImage"
              - "ecr:BatchCheckLayerAvailability"
              - "ecr:PutImage"
              - "ecr:InitiateLayerUpload"
              - "ecr:UploadLayerPart"
              - "ecr:CompleteLayerUpload"

Outputs:
  ECRRepository:
    Description: ECR repository
    Value: !Ref ECRRepository

The template above is responsible for creating the repo and proving an IAM user, specified in the YOUR_USER_NAME parameter, the necessary permissions to use the repository.

Note: Please replace YOUR_USER_NAME with your actual IAM username, or the creation will fail.

To deploy the template, run the following code:

aws cloudformation deploy --template-file ecr.yml --stack-name ecr-repository --capabilities CAPABILITY_NAMED_IAM --profile default --parameter-overrides IAMUserName=YOUR_USER_NAME

aws cloudformation deploy --template-file ecr.yml --stack-name ecr-repository --capabilities CAPABILITY_NAMED_IAM --profile default --parameter-overrides IAMUserName=YOUR_USER_NAME

Note:

  • The aws cloudformation deploy command specifies that we are trying to deploy a CloudFormation template.
  • --template-file is the path of the file that contains the template.
  • --stack-name is the name of the CloudFormation stack it will be deployed to. If a stack with that name exists, it will be updated, and if it doesn't, it will be created.
  • --capabilities must be specified before the resources can be created.
  • --profile is the name of the IAM profile being used.
  • --parameter-overrides are parameters in the template whose default values we want to change.

We can check the status of the stack creation by running:

AWS cloudformation describe-stacks --stack-name ecr-repository

Note:

  • The AWS cloudformation describe-stacks command specifies that we want to retrieve the information of a stack.
  • The --stack-name keyword is the name of the CloudFormation stack.

If it is created successfully, we should get an output with a StackStatus of CREATE_COMPLETE.

We can also check on the CloudFormation console in the region our default profile is set to.

CloudFormation Console
CloudFormation Console

Next, in the ECR console, our repository should be there.

ECR console showing newly created repository
ECR console showing newly created repository

Cleanup

Always clean up resources we don’t need to avoid unexpected bills.

To delete to the repository, run the following commands:

aws cloudformation delete-stack --stack-name ecr-repository

Note:

  • The aws cloudformation delete-stack command specifies that we want to delete a stack and the resources it created.
  • The --stack-name keyword is the name of the CloudFormation stack.

Confirm that the delete was successful by checking the status of the stack. Use the following command to do so:

AWS cloudformation describe-stacks --stack-name ecr-repository

Note: We can double-check in the AWS console to be sure.

Free Resources