TL:DR; CircleCI 2.0 now supports authenticating to AWS EC2 Container Registry (ECR) straight from the Docker executor. This means you can use private Docker images from ECR as your build image. View docs.

CircleCI 2.0 brought native Docker support. A project could be built on 2.0 with a public Docker image as the build environment. Crafting a lightweight CI environment customized to your project’s exact needs, and which could be snapshotted to be used over and over again, became commonplace. Users enjoyed having this ability but said they wanted support for private images as well. Not long after, the auth key was introduced to support logging into a Docker registry to pull a private image as your build environment:

jobs:
  build:
    docker:
      - image: acme-private/private-image:321
        auth:
          username: mydockerhub-user  # can specify string literal values
          password: $DOCKERHUB_PASSWORD  # or project UI environment variable reference

This works well for registries that support standard docker login credentials (i.e. Docker Hub). If you have a username and password for your Docker registry and that’s all you need, then you’re good. Enter AWS’s ECR.

AWS ECR provides a Docker registry service, but it doesn’t provide proper docker login credentials. Instead, per the AWS CLI Docs, you need to run aws ecr get-login which will generate a docker login shell command with temporary login credentials. These credentials only last for 12 hours making them not suitable for use in a CI environment.

We’ve now added baked-in support specifically for AWS ECR. You can start using private images from ECR in one of three ways:

  1. Set your AWS credentials using the CircleCI AWS Integration.
  2. Set your AWS credentials using standard CircleCI private environment variables.
  3. Specify your AWS credentials in .circleci/config.yml using aws_auth:
version: 2
jobs:
  build:
    docker:
      - image: account-id.dkr.ecr.us-east-1.amazonaws.com/org/repo:0.1
        aws_auth:
          aws_access_key_id: AKIAQWERVA  # can specify string literal values
          aws_secret_access_key: $ECR_AWS_SECRET_ACCESS_KEY  # or project UI envar reference

Options 2 & 3 are virtually the same except that 3 lets you specify whatever variable name you want for the credentials. This can come in handy where you have different AWS credentials for different infrastructure. For example, lets say your SaaS app runs the speedier tests and deploys to staging infrastructure on every commit while for Git tag pushes, we run the full-blown test suite before deploying to production:

version: 2
jobs:
  build:
    docker:
      - image: account-id.dkr.ecr.us-east-1.amazonaws.com/org/repo:0.1
        aws_auth:
          aws_access_key_id: $AWS_ACCESS_KEY_ID_STAGING
          aws_secret_access_key: $AWS_SECRET_ACCESS_KEY_STAGING
    steps:
      - run:
          name: "Every Day Tests"
          command: "testing...."
      - run:
          name: "Deploy to Staging Infrastructure"
          command: "something something darkside.... cli"
  deploy:
    docker:
      - image: account-id.dkr.ecr.us-east-1.amazonaws.com/org/repo:0.1
        aws_auth:
          aws_access_key_id: $AWS_ACCESS_KEY_ID_STAGING
          aws_secret_access_key: $AWS_SECRET_ACCESS_KEY_STAGING
    steps:
      - run:
          name: "Full Test Suite"
          command: "testing...."
      - run:
          name: "Deploy to Production Infrastructure"
          command: "something something darkside.... cli"

workflows:
  version: 2
  main:
    jobs:
      - build:
          filters:
            tags:
              only: /^\d{4}\.\d+$/
      - deploy:
          requires:
            - build
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^\d{4}\.\d+$/

Enjoy using private images from AWS ECR on CircleCI 2.0. Always take care to verify you’re not leaking any sensitive information in build output from the image or from private envars.