# Pushing Your Docker Image to AWS ECR

## **Introduction**

Before deploying ECS Fargate, you need to **store your Docker image in AWS ECR** (Elastic Container Registry). This guide covers ECR setup, Docker authentication, and the exact commands to push your image—all in 10 minutes.

**What You'll Learn:**

*   ✅ Create ECR repository (Terraform + AWS Console)
    
*   ✅ Authenticate Docker with AWS CLI
    
*   ✅ Build and tag your Docker image correctly
    
*   ✅ Push image to ECR (with error troubleshooting)
    
*   ✅ Configure ECS to pull from ECR
    

* * *

## **1\. Create ECR Repository**

**Option A: AWS Console (Quick)**

1.  Go to AWS Console → ECR
    
2.  Click "Create repository"
    
3.  Name: "ecs-app-repository"
    
4.  Tag visibility: "Public" (for development)
    
5.  Click "Create repository"
    

**Option B: Terraform (Production)**

```json
resource "aws_ecr_repository" "app" {
  name                 = "ecs-app-repository"
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }

  tags = {
    Name = "ecs-app-ecr"
  }
}

# Optional: Lifecycle policy (delete old images)
resource "aws_ecr_lifecycle_policy" "app" {
  repository = aws_ecr_repository.app.name

  policy = jsonencode({
    rules = [
      {
        rulePriority = 1
        description  = "Delete images older than 30 days"
        selection    = {
          tagStatus     = "any"
          countType     = "sinceImagePushed"
          countUnit     = "days"
          countNumber   = 30
        }
        action = {
          type = "expire"
        }
      }
    ]
  })
}
```

**Deploy:**

```json
terraform apply
```

**Expected Cost:**

*   ECR: $0.10/GB/month storage
    
*   First 500MB: Free (AWS free tier)
    

* * *

## **2\. Authenticate Docker with AWS CLI**

Before pushing, you need to **log in to ECR**:

```bash
# Get AWS credentials (if using IAM user)
aws configure

# Login Docker to ECR (macOS/Linux)
aws ecr get-login-password --region ap-south-1 | \
  docker login --username AWS --password-stdin \
  <your-aws-account-id>.dkr.ecr.ap-south-1.amazonaws.com

# Example output:
# Login succeeded
```

**Windows PowerShell:**

```powershell
$ECR_TOKEN = aws ecr get-login-password --region ap-south-1
$ECR_URI = "<your-aws-account-id>.dkr.ecr.ap-south-1.amazonaws.com"
docker login --username AWS --password $ECR_TOKEN $ECR_URI
```

**Troubleshooting:**

| Error | Fix |
| --- | --- |
| `access denied` | Check IAM permissions: `ecr:GetAuthorizationToken` |
| `region not found` | Use correct region: `ap-south-1` (Mumbai) |
| `docker not found` | Install Docker: `docker.io` |

* * *

## **3\. Build Your Docker Image**

Create a `Dockerfile` in your project root:

```docker
# Dockerfile
FROM node:18-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci --only=production

# Copy app code
COPY . .

# Expose port
EXPOSE 8080

# Start app
CMD ["npm", "start"]
```

**Build the image:**

```bash
docker build -t ecs-app:latest .
```

**Check it works locally:**

```bash
docker run -p 8080:8080 ecs-app:latest
# Visit: http://localhost:8080
```

* * *

## **4\. Tag Image for ECR**

You need to **tag your image with ECR URI**:

```bash
# Get ECR repository URI
ECR_URI="<your-aws-account-id>.dkr.ecr.ap-south-1.amazonaws.com/ecs-app-repository"

# Tag image
docker tag ecs-app:latest $ECR_URI:v1

# Example:
# docker tag ecs-app:latest 123456789012.dkr.ecr.ap-south-1.amazonaws.com/ecs-app-repository:v1
```

**Multiple versions:**

```bash
docker tag ecs-app:latest $ECR_URI:v2
docker tag ecs-app:latest $ECR_URI:latest
```

* * *

## **5\. Push Image to ECR**

```bash
docker push $ECR_URI:v1

# Expected output:
# The push refers to repository [123456789012.dkr.ecr.ap-south-1.amazonaws.com/ecs-app-repository]
# Try one more time...
# v1: pushing...
# Done!
```

**Check in AWS Console:**

1.  Go to ECR → ecs-app-repository
    
2.  Click "Images"
    
3.  You should see: v1 (pushed 2 mins ago)
    

* * *

## **6\. Configure ECS to Pull from ECR**

In your ECS task definition (Part 3), add:

```bash
resource "aws_ecs_task_definition" "app" {
  family = "ecs-app-task"

  container_definitions = jsonencode([
    {
      name      = "ecs-app"
      image     = "${aws_ecr_repository.app.repository_url}:v1"
      memory    = 512
      portMappings = [
        {
          containerPort = 8080
          hostPort      = 8080
        }
      ]

      # ECR authentication (automatically handled)
      environment = [
        {
          name  = "NODE_ENV"
          value = "production"
        }
      ]
    }
  ])

  # Fargate profile
  capacityProviderStrategy = [
    {
      capacityProvider = "FARGATE"
      weight           = 1
    }
  ]
}
```

* * *

## **Common Errors & Fixes**

| Error | Cause | Solution |
| --- | --- | --- |
| `access denied` | IAM missing `ecr:PutImage` | Add IAM policy |
| `no such image` | Wrong image name | Check `docker images` |
| `timeout` | Slow internet | Retry or use AWS CLI |

* * *

## **Summary**

You now have your Docker image in **AWS ECR**:

*   ✅ ECR repository created (Terraform)
    
*   ✅ Docker authenticated with AWS
    
*   ✅ Image built, tagged, and pushed
    
*   ✅ ECS configured to pull from ECR
    

**Next Step:** Part 3 will deploy the **ECS Fargate cluster** with Terraform.
