In modern cloud architectures, container images are the building blocks of your microservices, and having a private, secure, managed image registry is essential. Amazon ECR (Elastic Container Registry) fills that role in the AWS ecosystem. In this post, I will walk through how to create a private ECR repository, use it in both ECS (Elastic Container Service) and EKS (Elastic Kubernetes Service). Along the way you’ll see how to manage permissions, authenticate, push images, and reference them in your deployments.

Prerequisites and assumptions

I assume you already have an AWS account, the AWS CLI installed and configured with appropriate credentials, and basic familiarity with Docker. If not, no point of moving forward. Furthermore, I will use placeholder names like “my-private-app” or account id “123456789012”. Feel free to modify them. For ECS you’ll need a cluster (either EC2-backed or Fargate). For EKS you’ll have a Kubernetes cluster running (or you can create one). Let’s begin.

Step 1: Create a private ECR repository

First, create the ECR repository into which you’ll push your container images. Using AWS CLI:

aws ecr create-repository \
  --repository-name my-private-app \
  --image-scanning-configuration scanOnPush=true \
  --region us-east-1

This command creates a repository named my-private-app in the us-east-1 region and enables scanning of images on push. You can adjust settings (lifecycle policies, encryption, tags) as needed via the console or CLI.

Verify the repository exists:

aws ecr describe-repositories --repository-names my-private-app --region us-east-1

You’ll see repository metadata including URI (for example 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-app).

Step 2: Configure IAM permissions for pushing and pulling

To allow pushing images, your CI system or your local user must have IAM permissions. A minimal policy might look like:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:BatchGetImage",
        "ecr:BatchCheckLayerAvailability",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:GetAuthorizationToken"
      ],
      "Resource": "arn:aws:ecr:us-east-1:123456789012:repository/my-private-app"
    }
  ]
}

Also, the principal will need sts:GetServiceBearerToken or equivalent implicitly via ECR permissions. Make sure your IAM role or user can retrieve the ECR authorization token.

Step 3: Authenticate Docker to ECR

Before pushing images, you must authenticate Docker (or your container tool) against ECR. With the AWS CLI v2:

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com

This command fetches an authentication token and pipes it into docker login, so your Docker client can push into that registry.

Step 4: Build and push your Docker image

Tag and push:

docker build -t my-private-app:latest .
docker tag my-private-app:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-app:latest
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-app:latest

If the push succeeds, your image now resides in the private ECR repository and is available for ECS or EKS to pull.

Step 5: Use the image in ECS

In ECS, define a task definition that references the ECR image. Example JSON excerpt:

{
  "containerDefinitions": [
    {
      "name": "my-app",
      "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-app:latest",
      "portMappings": [
        {
          "containerPort": 8080,
          "hostPort": 8080
        }
      ],
      "essential": true
    }
  ],
  "family": "my-app-task"
}

When ECS launches a task on EC2 or Fargate, it automatically retrieves an authorization token (assuming your ECS task role has the right policies) and pulls from ECR. If you are using EC2 instances, make sure the instances’ IAM role (the instance profile) includes AmazonEC2ContainerRegistryReadOnly or equivalent.

Deploy or update a service using that task definition. The service scheduler ensures the container is launched with the right image.

Step 6: Use the image in EKS

In EKS, your pods must also be able to pull from the private registry. There are two common approaches: using IAM roles for service accounts (IRSA) or using a Kubernetes secret of type docker-registry.

If you use IRSA, create an IAM role that your service account will assume. That IAM role needs policies similar to ECR pull permissions:

{
  "Effect": "Allow",
  "Action": [
    "ecr:GetAuthorizationToken",
    "ecr:BatchCheckLayerAvailability",
    "ecr:GetDownloadUrlForLayer",
    "ecr:BatchGetImage"
  ],
  "Resource": "*"
}

Annotate your Kubernetes service account with that IAM role:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/EksEcrPullRole

Then in your Deployment or Pod spec, reference that service account. Kubernetes will assume that IAM role and allow the pod to pull from ECR without needing a secret.

If you prefer the classic method, create a docker-registry secret:

kubectl create secret docker-registry ecr-registry-secret \
  --docker-server=123456789012.dkr.ecr.us-east-1.amazonaws.com \
  --docker-username=AWS \
  --docker-password=$(aws ecr get-login-password --region us-east-1) \
  --docker-email=you@example.com

Then in your Deployment spec:

spec:
  template:
    spec:
      imagePullSecrets:
        - name: ecr-registry-secret

And your container spec:

containers:
  - name: my-app
    image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-app:latest

When Kubernetes schedules the pod, it uses that secret to authenticate to ECR and pull the image.

Remember that ECR tokens expire, so any long-running authentication must be refreshed. That’s why IRSA is cleaner in EKS, because the pods re-assume roles transparently. Also, enabling image scanning on push allows you to detect known vulnerabilities. For lifecycle management, you can add retention rules to prune old images automatically. Monitor your ECR storage and costs especially if you accumulate many versions. For cross-account or cross-region use, you may need to adjust repository policies or replicate images to a target region.

Suleyman Cabir Ataman, PhD

Sharing on social media:

Leave a Reply

Your email address will not be published. Required fields are marked *