This article is an introduction to using CircleCI orbs to build and push production-grade Docker images to the Amazon Elastic Container Registry (ECR) for storage.

What is Amazon ECR?

Amazon ECR is a fully-managed, private Docker container registry that makes it easy for developers to store, manage, and deploy Docker container images. Amazon ECR integrates seamlessly with Amazon Elastic Container Service Amazon ECSe and Amazon Elastic Kubernetes Service Amazon EKS. Amazon ECR can also be used with other cloud vendors.

Why would you want to use a private Docker registry like Amazon ECR?

  • In many circumstances, it is desirable to segregate the development, test, and production registries.
  • It’s fully managed which eliminates the need to operate your own container repositories or worry about scaling the underlying infrastructure.
  • It’s secure. A private container registry with scanning capabilities and role-based access control offers more security, governance (IAM), and efficient management. It transfers your container images over HTTPS and automatically encrypts your images at rest.
  • Running registries close to the systems running the containers cuts deployment latency and reduces exposure to network outages.

Developers need to use a registry to store images created during the application development process. Continuous integration pipelines connect building container images and pushing these artifacts into Amazon ECR. Imagine a pipeline where you push a commit that triggers a build on CircleCI that pushes a new image into Amazon ECR. Your registry can then fire off a webhook and trigger a deployment. All without a human having to manually do anything. Registries make a fully automated pipeline like this much easier. Container images placed in the registry can then be used in various phases of the development. In a few steps, using CircleCI orbs, we are going to containerize a simple Node.js application, build the image, and push it to Amazon ECR.

Setting up Amazon ECR

From the AWS management console, select IAM. This service lets you manage access to AWS resources.

AWS management console

Create a role/user. I called mine ci-cd-ecr, but any name will work. Make sure you select the Access key - Programmatic access option.

Create role/user

Next, set permissions for the user. Click Attach existing policies directly. The screenshot shows what you need to successfully create a private repository for your image on AWS and have full access for other modifications.

Set permission

Click Next twice to create the new user.

You will be greeted with a success message along with your user credentials. This page is only displayed once so make a note of the Access Key ID and the Secret access key which will be used later on. Alternatively, you can download the csv file provided which contains the same credentials.

User credentials

Setting up a CircleCI pipeline using the AWS-ECR orb

The code for this demo is available on GitHub here. Clone the application using the following command:

git clone https://github.com/CIRCLECI-GWP/circleci-ecr-demo

Find the CircleCI config file in the .circleci/ folder. Using orbs, as you’ll see, you can build an image and push it to Amazon ECR using only 13 lines of config! The aws-ecr orb comes prepackaged with commands to:

  • Build an image
  • Login to Amazon ECR
  • Create an Amazon ECR repo, if one doesn’t exist
  • Push an image to Amazon ECR

Here is the full config for your pipeline:

version: 2.1

orbs:
  aws-ecr: circleci/aws-ecr@8.1.3

workflows:
  build_and_push_image:
    jobs:
      - aws-ecr/build-and-push-image:
          context: aws-dev
          create-repo: true
          dockerfile: Dockerfile
          path: .
          repo: circleci-ecr-demo
          tag: "$CIRCLE_SHA1"

This configuration file uses Amazon Elastic Container Registry orb to build and deploy Docker image. The dockerfile: command specifies the path to your Dockerfile. The demo repo uses the following Dockerfile:

# Set the base image to use for subsequent instructions
FROM node:alpine

# Add metadata to an image
LABEL app="simple-node-application"
# Directive to set environmental variables key to value pair
ENV NPM_CONFIG_LOGLEVEL warn

# Set the working directory for any subsequent ADD, COPY, CMD, ENTRYPOINT,
# or RUN instructions that follow it in the Dockerfile
WORKDIR /usr/src/app

# Copy files or folders from source to the dest path in the image's filesystem.
COPY package.json /usr/src/app/
COPY . /usr/src/app/

# Execute any commands on top of the current image as a new layer and commit the results.
RUN npm install --production

# Define the network ports that this container will listen on at runtime.
EXPOSE 3000

# Configure the container to be run as an executable.
ENTRYPOINT ["npm", "start"]

Adding Context and setting up environment variables for Amazon ECR

In your CircleCI dashboard, go to the Organization Settings page by clicking on the link in the sidebar. Next, select Context. Click the Create Context button and add a unique name for your Context. The Context appears in a list with Security set to All members to indicate that anyone in your organization can access this Context at runtime. As specified in the .circleci/config.yml configuration for this tutorial, the Context name should be aws-dev.

Create Contexts

Next, select the aws-credentials context.

Create environment variables

Click the Add Environment Variable button. Enter the variable name and value you want to associate with this context. Click the Add Variable button to save. The aws-dev context requires these three environment variables:

  • AWS_ACCESS_KEY_ID is the AWS access key id for the ci-cd-ecr IAM role you created earlier.
  • AWS_SECRET_ACCESS_KEY is the AWS secret key for the ci-cd-ecr IAM role that you created earlier.
  • AWS_ECR_REGISTRY_ID is the 12 digit AWS id associated with the ECR account. This is also known as account ID.
  • AWS_REGION is the AWS region where your ECR resources will be located.

Note: You don’t have to set $CIRCLE_SHA1 because it is the default variable available in all CircleCI projects. It’s the SHA1 hash of the last commit of the current build. Using the Git commit hash gives you the ability to trace what’s in the containers. Ideally, it allows you to trace a container back to its Docker image, and then back to the Dockerfile and code contained in the image. In an automated execution environment, this will take you back to the commit that caused the Docker image to be built.

Connecting the application to CircleCI

The next step is to set up a repository on GitHub and link the project to CircleCI. Review Pushing a project to GitHub for instructions.

Log in to your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard. Locate your project (circleci-ecr-demo in this case) and click Set Up Project.

Select project

Enter the name of the branch where your code is housed on GitHub and click Set Up Project.

Your first workflow will start running and complete successfully.

Build and deployed successfully

To review the repository information, go to your AWS management Console.

Conclusion

With both CircleCI and Amazon ECR successfully configured, you can start building images and pushing them to the repository.

With just a few lines of code, you were able to build and push your Docker image to Amazon ECR. CircleCI orbs save time by importing pre-built commands, jobs, and executors into CircleCI configuration files, providing easy integration with cloud services and other tools.


Dominic Motuka is a DevOps Engineer at Andela with 4+ years of hands-on experience supporting, automating, and optimizing production-ready deployments in AWS and GCP, leveraging configuration management, CI/CD, and DevOps processes.

Read more posts by Dominic Motuka