Containers

Using Amazon ECR replication rules to optimize your application delivery process

Last year, we released cross region replication (CRR) in Amazon Elastic Container Registry (Amazon ECR) to allow you to configure the replication for your private registry across different regions and accounts. This allowed our customers to focus on applications and value to their organizations , leaving the undifferentiated heavy lifting to AWS to manage replication of images from one location to another.

At AWS, customer feedback plays a big role in the services and features we launch. Three days after we released the feature, our customers asked for a further enhancement that would offer more control over which images should be replicated between regions, allowing them to optimize their environment and reduce costs.

In this blog, I’m going to expand on the example from the post above and demonstrate how this feature gives you even more control with your Docker images in Amazon Elastic Container Registry (ECR), using a real world scenario.

Solution overview

A development team is working on a containerized application. As part of their daily process, the dev team pushes multiple changes into their ECR repo in the source Region us-west-2. Until today, these changes were replicated to the production account Region us-west-2 using CRR, but the deploy team prefers to only store and deploy the builds that are stable and tagged production ready.

Note: AWS recommends that our customers keep their test and production accounts separate. You can find more information In the Organizing Your AWS Environment Using Multiple Accounts whitepaper.

The dev team puts the development changes through a pipeline to confirm that the feature behaves and performs as expected, and then a tag is added to the image to promote it to the next stage, ready for production. The artifacts that are used throughout the development process are not replicated to the production account. Once the image has been tagged correctly, it will be replicated to the production account and the deploy team will pick up the new image and release the change into production. The following diagram describes this process.

Deployment steps

Prerequisites:

  • Two AWS accounts (in this example Dev is 111122223333 and Production is 444455556666)
  • AWS CLI
  • Docker client

To simulate this scenario, I create two ECR repositories in the Dev account, one to simulate the development changes and the second for production changes. I create a simple Docker image in the dev account, iterate on that image, tag it ready for production use, and observe the replication of only these changes to the production account.

First we are going to set up the ECR registry in the dev account. Open Amazon ECR in the AWS Management Console → Private registry → Replication Configuration → Add rule.

I am going to enable Cross-account replication.

I enter the account number for the production account and us-west-2 as my destination Region.

To avoid replicating every single change that is pushed to the ECR repo, I am going to add a filter to match a specific pattern, and only the matching images will be replicated. In my case, I am using the prefix of prod-microservice to identify that the image has gone through the necessary testing and is ready for production.

On the last screen, you will confirm your settings and select Submit rule.

You can also see the JSON syntax in the console if you would like to perform these actions through the CLI.

I am now going to switch over to the production account. In order to allow incoming ECR replication, the destination repository needs a set of permissions. This was highlighted above in the console during the rule creation and is documented here.

Open the ECR in the AWS Management Console in the destination Region (us-east-2) and select Private registry then navigate to Permissions and click Generate statement.

Choose Cross account policy for the policy type, add `ReplicationAccessCrossAccount`
as the Statement id, enter the account id from your source account (111122223333), and select Add to policy.

I am going to switch over to the CLI and run the rest of the commands from there. First I am going to create two repositories dev-microservice and prod-microservice.

aws ecr create-repository --region us-west-2 —repository-name dev-microservice
aws ecr create-repository --region us-west-2 —repository-name prod-microservice

I am then going to create a simple Dockerfile in my current working directory running Apache with a simple index.html .

cat > ./Dockerfile << EOF

FROM public.ecr.aws/amazonlinux/amazonlinux:latest

# Install dependencies
RUN yum install -y httpd

# Install apache and write hello world message
RUN echo 'Hello World!'> /var/www/html/index.html

# Configure apache
RUN echo 'mkdir -p /var/run/httpd' >> /root/run_apache.sh && \
echo 'mkdir -p /var/lock/httpd' >> /root/run_apache.sh && \
echo '/usr/sbin/httpd -D FOREGROUND' >> /root/run_apache.sh && \
chmod 755 /root/run_apache.sh

EXPOSE 80

CMD /root/run_apache.sh

EOF

Authenticate to your source region ECR repository (remember to replace 111122223333 with your own account ID).

aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 111122223333.dkr.us-west-2.amazonaws.com

Build the image.

docker build -t hello-world .

This simulates the dev team’s work iterating on the image. I am going to add the dev-microservice tag to the image and push it to ECR.

docker tag hello-world 111122223333.dkr.us-west-2.amazonaws.com/dev-microservice:42
docker push 111122223333.dkr.us-west-2.amazonaws.com/dev-microservice:42

The filter configured was for prod-microservice, so no replication to another account will occur. After the image passes through the dev teams tests in the pipeline, I can tag it for production use with an appropriate version, so that the deploy team can release the new feature.

docker tag 111122223333.dkr.us-west-2.amazonaws.com/dev-microservice:42 111122223333.dkr.us-west-2.amazonaws.com/prod-microservice:21

Push the image to ECR.

docker push 111122223333.dkr.us-west-2.amazonaws.com/prod-microservice:21

This is the image in the dev account.

By switching over to the console in us-west-2 in the production account (444455556666), I can see the following.

The production change was replicated to the production account, but none of the iterations on the development repository were replicated. You will notice that I did not need to create the repository in the destination account, this was created automatically once the replication was triggered.

Cleanup

To delete the resources that you created in this post, execute the following steps.

  • in your dev account (111122223333)
    • delete the two ECR repositories that you created (dev-microservice and prod-microservice)
    • delete the replication configuration rule
  • in your production account (444455556666)
    • delete the prod-microservice ECR repository
    • remove the private registry permission statement
  • on your local computer
    • remove the Dockerfile that you created
    • remove the docker images that you created for this blog post

Wrapping up

In the beginning of this blog, we talked about some of the challenges customers face specifically around replication of docker images from one region to another and also between accounts. Today, this new ability to filter which images are replicated to other accounts or regions is available to allow customers to offload the heavy lifting of self-managing the replication of artifacts between different teams and locations.

We are continuing to make improvements on behalf of our customers, and welcome your suggestions for new features or issues that you’d like to share. Please check out our public roadmap to find existing feature requests or submit a new one.