28.2 Pushing and Pulling Images with Docker CLI and aws ecr get-login-password
Right, so you’ve got an image built and you’re ready to stash it somewhere AWS can actually use it. That somewhere is ECR, and getting your image in and out is our only job right now. It’s a simple process, but AWS, in its infinite wisdom, has made the authentication part just convoluted enough to be a consistent pain point. We’re going to conquer it. Not just the “how,” but the “why the hell does it work like this?”
First, let’s get our terms straight. An ECR “repository” is just a fancy named bucket for your Docker images. You push to it and pull from it. Before you can do either, you need to prove to the Docker CLI that you’re allowed to talk to it. Docker expects credentials, but it doesn’t speak IAM natively. This is where the ceremony begins.
The Authentication Two-Step (and why it feels clunky)
Docker prefers to be logged in using a username and password. AWS doesn’t hand out passwords willy-nilly; it uses IAM credentials. The magic glue is the aws ecr get-login-password command. What this does is call the AWS API, and if your IAM user/role has permission, it returns a single-use, short-lived authorization token that just so happens to work as a Docker password.
The old way involved piping this into a docker login command with some gnarly syntax. The new way is cleaner, but you still have to do it every 12 hours because that token expires. It’s a bit of a dance, but you get used to it.
Here’s the incantation. Make sure your AWS CLI is configured with credentials that have permissions for ECR (the AmazonEC2ContainerRegistryFullAccess managed policy is the easy button for learning).
# Replace region and account ID with yours. No, really, please do.
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
The --password-stdin flag is crucial for security—it takes the password from standard input instead of the command line, where it could be snooped on. If that command succeeds, your Docker client is now authenticated to talk to all repositories in that specific account and region. You’re logged in.
Actually Pushing an Image
You can’t just push an image named my-app:latest. Docker doesn’t know that’s destined for ECR. You have to tag it with the full ECR repository URI first. It’s like putting the correct address on a package.
First, create the repository if it doesn’t exist. This is a one-time operation.
aws ecr create-repository --repository-name my-cool-app --region us-east-1
Now, tag your local image. Find your image’s ID with docker images.
# Tag the image, mapping it to your ECR repo
docker tag my-cool-app:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-cool-app:latest
Finally, push it. This part is anti-climactically simple after all that setup.
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-cool-app:latest
Watch the output. You’ll see all the image layers being pushed up. If it fails partway through, Docker is smart enough to just push the missing layers next time.
Pulling It Back Down
Pulling is essentially the reverse, and you might need to do this if you’re setting up a machine that needs to run the image. If it’s been more than 12 hours, you’ll need to re-run the get-login-password command first. Then, just pull using the full tag.
docker pull 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-cool-app:latest
Common Facepalms and How to Avoid Them
- The “no basic auth credentials” error: This is Docker’s profoundly unhelpful way of saying “you’re not logged in” or your token expired. Your first step is always to re-run the login command.
- Wrong Region: You’re authenticated to
us-east-1but trying to push to a repo inus-west-2. The login is region-specific. Double-check your--regionflag and your repository’s URI. - Permission Errors:
get-login-passwordworked, butdocker pushfails? Your IAM identity might have permission to get the login token but not to actually push to the repository. Check the repository’s resource-based policy and your IAM permissions. The error message fromdocker pushis usually useless; check CloudTrail for the real IAM denial message. - Forgetting to Tag: You’ll try to push
my-app:latestand Docker will have no idea what repository you’re talking about. Always tag with the full URI.
It feels like a few too many steps, and it is. You’ll eventually script this or use a tool that handles it for you. But understanding the dance is key to debugging it when the music stops, which it will. Now go forth and push.