# Push Docker Images from Rancher Desktop to Amazon ECR

> Create an Amazon ECR repository with Terraform, log in with the AWS CLI and push images built in Rancher Desktop with docker or nerdctl, for ECS and EKS.

- Source: https://www.itwonderlab.com/rancher-desktop-push-images-aws-ecr/
- Published: 2026-10-06
- Updated: 2026-10-06
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

## Why a registry

Images built on your laptop work for local development, but the rest of the world needs them in a **registry**: your [ECS](https://www.itwonderlab.com/aws-ecs/) services, [EKS](https://www.itwonderlab.com/aws-eks/) nodes and CI pipelines pull from there. [Amazon ECR](https://www.itwonderlab.com/aws-ecr/) is the private registry of AWS: it integrates with [IAM](https://www.itwonderlab.com/aws-iam/), scans images and has no extra servers to run.

![Push an image from Rancher Desktop to Amazon ECR: aws ecr get-login-password logs docker in, docker tag adds the registry name and docker push uploads the image, which ECS or EKS then pulls](https://www.itwonderlab.com/media/tutorials/Diagrams/ITWL-ECR-Push.svg "Login, tag and push")

## Prerequisites

- [Rancher Desktop installed](https://www.itwonderlab.com/rancher-desktop-install/) and an image to push, such as `myapp:1.0` from the [Dockerfile tutorial](https://www.itwonderlab.com/dockerfile-tutorial/).
- The [AWS CLI installed](https://www.itwonderlab.com/install-aws-cli/) and configured, with credentials that can use ECR.
- Optional: [Terraform or OpenTofu](https://www.itwonderlab.com/aws-terraform-tutorial-terraform-basics/) to create the repository as code.

## Create the repository with Terraform

```hcl title="ecr.tf"
resource "aws_ecr_repository" "app" {
  name                 = "myapp"
  image_tag_mutability = "IMMUTABLE"   # a pushed tag can never be overwritten

  image_scanning_configuration {
    scan_on_push = true
  }

  encryption_configuration {
    encryption_type = "KMS"            # use the AWS managed key for ECR; add kms_key for your own
  }
}

# Delete untagged images after 14 days to control the cost
resource "aws_ecr_lifecycle_policy" "app" {
  repository = aws_ecr_repository.app.name

  policy = jsonencode({
    rules = [{
      rulePriority = 1
      description  = "Expire untagged images after 14 days"
      selection = {
        tagStatus   = "untagged"
        countType   = "sinceImagePushed"
        countUnit   = "days"
        countNumber = 14
      }
      action = { type = "expire" }
    }]
  })
}

output "repository_url" {
  value = aws_ecr_repository.app.repository_url
}
```

```shell
$ terraform init
$ terraform apply
repository_url = "123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp"
```

Or with the AWS CLI:

```shell
$ aws ecr create-repository --repository-name myapp \
    --image-scanning-configuration scanOnPush=true --image-tag-mutability IMMUTABLE
```

## Log in

ECR does not use a permanent password. The AWS CLI gets a token valid for 12 hours and you give it to the engine:

```shell
$ REGISTRY=123456789012.dkr.ecr.us-east-1.amazonaws.com

# dockerd
$ aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $REGISTRY
Login Succeeded

# containerd
$ aws ecr get-login-password --region us-east-1 | nerdctl login --username AWS --password-stdin $REGISTRY
```

> [!TIP]
> To avoid logging in every 12 hours, install the [Amazon ECR credential helper](https://github.com/awslabs/amazon-ecr-credential-helper) and add `{"credHelpers": {"123456789012.dkr.ecr.us-east-1.amazonaws.com": "ecr-login"}}` to `~/.docker/config.json`. It asks AWS for a fresh token whenever it is needed, using your normal AWS credentials.

## Tag and push

An image name must contain the registry address to be pushed there. Add a second name (a tag) to your image:

```shell
$ docker tag myapp:1.0 $REGISTRY/myapp:1.0
$ docker push $REGISTRY/myapp:1.0
```

With nerdctl the commands are the same: `nerdctl tag ...` and `nerdctl push ...`. Check the result and the scan:

```shell
$ aws ecr describe-images --repository-name myapp
$ aws ecr describe-image-scan-findings --repository-name myapp --image-id imageTag=1.0
```

## Build for the right architecture

If your laptop is an Apple Silicon Mac and your cluster or Fargate tasks run on `amd64` (or the opposite), an image built for the wrong architecture fails at start with `exec format error`. Build for the target platform, or for both:

```shell
$ docker buildx build --platform linux/amd64 -t $REGISTRY/myapp:1.0 --push .
```

The [BuildKit tutorial](https://www.itwonderlab.com/docker-buildkit-buildx/) explains multi-platform builds.

## Pull from ECS and EKS

- **ECS and Fargate**: the *task execution role* must be allowed to pull. Attach the AWS managed policy `AmazonECSTaskExecutionRolePolicy` and use the full image URI in the task definition. See [ECS with Terraform and Fargate](https://www.itwonderlab.com/containers-aws-ecs-terraform-fargate/).
- **EKS**: the node IAM role needs `AmazonEC2ContainerRegistryReadOnly`, or the equivalent permissions for pods that use IAM roles. See [EKS with Terraform](https://www.itwonderlab.com/terraform-eks/).

## Permissions to push

A user or CI role that only pushes needs these actions (and `ecr:GetAuthorizationToken` on all resources):

```json
{
  "Effect": "Allow",
  "Action": [
    "ecr:BatchCheckLayerAvailability",
    "ecr:InitiateLayerUpload",
    "ecr:UploadLayerPart",
    "ecr:CompleteLayerUpload",
    "ecr:PutImage"
  ],
  "Resource": "arn:aws:ecr:us-east-1:123456789012:repository/myapp"
}
```

For automated pushes, use a role from your pipeline with OIDC instead of access keys, as in [Terraform with GitHub Actions and AWS OIDC](https://www.itwonderlab.com/terraform-github-actions-aws-oidc/).

## Clean up

```shell
$ docker logout $REGISTRY
$ terraform destroy        # or: aws ecr delete-repository --repository-name myapp --force
```

## Next steps

Manage Docker resources as code with the [Terraform Docker provider](https://www.itwonderlab.com/terraform-docker-provider/).
