All Articles

AWS ECR Image Push Access Denied — Every Fix (2026)

docker push to ECR fails with 'Access Denied' or 'no basic auth credentials'. Here's every cause — expired token, wrong region, missing IAM permissions, ECR URI mismatch — and the exact fix for each.

DevOpsBoysApr 23, 20264 min read
Share:Tweet

You run docker push to your AWS ECR repository and get:

denied: User: arn:aws:iam::123456789:user/deploy is not authorized to perform: ecr:InitiateLayerUpload

or

no basic auth credentials

or

Error response from daemon: Get "https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/": unauthorized

Here's every cause and the exact fix.


How ECR Authentication Works

ECR uses temporary Docker credentials that expire after 12 hours. The flow:

  1. You call aws ecr get-login-password → AWS returns a temporary password
  2. You run docker login with that password → Docker stores it locally
  3. Now you can push/pull for up to 12 hours

If anything breaks in this chain, you get access denied.


Fix 1: Re-authenticate (Most Common Cause)

Your ECR token expired. This is the most common cause, especially in CI/CD pipelines.

bash
# Authenticate Docker to ECR — run this FIRST every time
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  123456789012.dkr.ecr.us-east-1.amazonaws.com

Replace:

  • us-east-1 with your actual ECR region
  • 123456789012 with your actual AWS account ID

After this succeeds, retry your push.

In CI/CD pipelines: Run this command at the start of every job that pushes to ECR. Don't cache ECR credentials between pipeline runs.


Fix 2: Wrong Region in the ECR URI

Symptom: Auth succeeds but push fails with no basic auth credentials for a different registry.

bash
# Check your ECR URI carefully
# WRONG — region mismatch
aws ecr get-login-password --region us-east-1 | docker login ... us-west-2.amazonaws.com
 
# The auth was for us-east-1 but you're pushing to us-west-2
docker push 123456789.dkr.ecr.us-west-2.amazonaws.com/myapp:latest
# FAILS — different registry, not authenticated

Fix: Make sure the region in your get-login-password matches the region in your ECR repository URI. If your repo is in ap-south-1, authenticate against ap-south-1.

bash
REGION="ap-south-1"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ECR_REGISTRY="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com"
 
aws ecr get-login-password --region $REGION | \
  docker login --username AWS --password-stdin $ECR_REGISTRY
 
docker push $ECR_REGISTRY/myapp:latest

Fix 3: Missing IAM Permissions

Symptom: Authentication works but push fails with explicit deny:

denied: User: arn:aws:iam::123456789:user/ci-user is not authorized to perform: ecr:InitiateLayerUpload

Check the user's permissions:

bash
aws iam get-user --user-name ci-user
aws iam list-attached-user-policies --user-name ci-user
aws iam list-user-policies --user-name ci-user

Required IAM permissions for ECR push:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:GetRepositoryPolicy",
        "ecr:DescribeRepositories",
        "ecr:ListImages",
        "ecr:DescribeImages",
        "ecr:BatchGetImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:PutImage"
      ],
      "Resource": "arn:aws:ecr:us-east-1:123456789012:repository/myapp"
    }
  ]
}

Attach this policy to your IAM user or role. Note: ecr:GetAuthorizationToken must apply to * (it's account-level, not repository-level).


Fix 4: ECR Repository Doesn't Exist Yet

Symptom:

name unknown: The repository with name 'myapp' does not exist in the registry with id '123456789012'

You need to create the repository first:

bash
aws ecr create-repository \
  --repository-name myapp \
  --region us-east-1 \
  --image-scanning-configuration scanOnPush=true \
  --encryption-configuration encryptionType=AES256

Then push.


Fix 5: ECR Repository Policy Denying Access

ECR has resource-based policies separate from IAM policies. A restrictive repository policy can deny access even to admins.

Check the repository policy:

bash
aws ecr get-repository-policy \
  --repository-name myapp \
  --region us-east-1

If there's an explicit Deny, fix or remove it:

bash
# Remove the repository policy entirely (revert to IAM-only control)
aws ecr delete-repository-policy \
  --repository-name myapp \
  --region us-east-1

Or update the policy to allow your user/role:

bash
aws ecr set-repository-policy \
  --repository-name myapp \
  --region us-east-1 \
  --policy-text '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "AllowPush",
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::123456789012:role/ci-role"
        },
        "Action": [
          "ecr:BatchCheckLayerAvailability",
          "ecr:PutImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload"
        ]
      }
    ]
  }'

Fix 6: Cross-Account ECR Access

Symptom: You're pushing from Account A to a repository in Account B.

Fix: The ECR repository in Account B needs a resource-based policy allowing Account A:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CrossAccountPush",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::ACCOUNT_A_ID:root"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer"
      ]
    }
  ]
}

And the entity in Account A still needs ecr:GetAuthorizationToken permission.


Fix 7: GitHub Actions / CI-specific Issues

Problem: ECR auth works locally but fails in CI.

yaml
# GitHub Actions — correct ECR auth pattern
- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: us-east-1
 
- name: Login to Amazon ECR
  id: login-ecr
  uses: aws-actions/amazon-ecr-login@v2
 
- name: Build and push
  env:
    REGISTRY: ${{ steps.login-ecr.outputs.registry }}
    IMAGE_TAG: ${{ github.sha }}
  run: |
    docker build -t $REGISTRY/myapp:$IMAGE_TAG .
    docker push $REGISTRY/myapp:$IMAGE_TAG

Use the official amazon-ecr-login action — it handles authentication automatically including the region detection.


Debugging Checklist

Run through this when ECR push fails:

bash
# 1. Check your AWS identity
aws sts get-caller-identity
 
# 2. Re-authenticate to ECR
aws ecr get-login-password --region YOUR_REGION | \
  docker login --username AWS --password-stdin YOUR_ACCOUNT.dkr.ecr.YOUR_REGION.amazonaws.com
 
# 3. Check repository exists
aws ecr describe-repositories --repository-names YOUR_REPO --region YOUR_REGION
 
# 4. Verify IAM permissions (simulate the API call)
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789:user/ci-user \
  --action-names ecr:InitiateLayerUpload \
  --resource-arns arn:aws:ecr:us-east-1:123456789:repository/myapp
 
# 5. Check repository policy
aws ecr get-repository-policy --repository-name YOUR_REPO --region YOUR_REGION

The simulate-principal-policy command is invaluable — it tells you exactly whether a specific action is allowed or denied and why.


ECR access issues almost always come down to expired tokens, wrong region, or missing IAM permissions. The debugging checklist above catches 95% of cases in under 5 minutes.

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments