Deploying Docker Containers to Elastic Beanstalk from ECR

By Andrew Siemer · August 6, 2026

← All insights

Todd deploying containers to the cloud

You have a Docker image sitting in Amazon ECR and you want it running in the cloud without hand-rolling a whole ECS cluster, a load balancer, and a pile of Terraform. Elastic Beanstalk is still one of the fastest ways to get there. It hands you an EC2 instance, health checks, rolling deploys, and HTTPS with almost no ops overhead - you just point it at a container and go.

The catch is that Beanstalk's Docker story has changed a lot since the early days, and a good chunk of the tutorials you will find are describing a platform that no longer exists. Here is how it actually works today, plus the two or three places that will still trip you up.

First, is Beanstalk even the right tool?

Quick gut check before you commit. If you want the lowest-ops path for a single web container, AWS App Runner is now the more direct answer - point it at ECR, done. If you need real orchestration, multiple services, or fine-grained scaling, ECS on Fargate is where you want to live.

Beanstalk sits in the middle, and it is still a great fit when you want a normal EC2 environment you can SSH into, full control over the instance, and a deploy story that is basically "run one command." It is boring in the good way. If that is your project, keep reading.

Log Docker into ECR

The first thing that bites people: the old aws ecr get-login command is gone. It was removed in AWS CLI v2 years ago, and if you copy it out of an ancient blog post you will get a cryptic failure about an unknown flag. Do not chase that error - the command simply does not exist anymore.

The current one-liner pipes a token straight into docker login over stdin, which is also more secure because your password never lands in shell history:

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

That is it. Login Succeeded and you can push. Tag and push your image the usual way:

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

Set up the Beanstalk app

Install the EB CLI, then run eb init inside your project directory. It walks you through picking a region, naming the application, and choosing a platform - pick the current Docker running on Amazon Linux 2023 branch. Your answers get saved to a hidden .elasticbeanstalk/ folder so future eb commands remember them.

Here is the single most important detail, and it has not changed: Beanstalk decides how to deploy based on what files are in your directory.

  • If there is a Dockerfile, Beanstalk builds the image on the environment itself, on every deploy.
  • If there is a Dockerrun.aws.json and no Dockerfile, Beanstalk pulls a pre-built image from ECR.

Those two are mutually exclusive. If you want to deploy the image you already pushed to ECR - which you do, because building on the box is slow and non-reproducible - delete the Dockerfile from the deploy directory and use Dockerrun.aws.json.

The Dockerrun.aws.json file

For a single-container environment this file is short. Note it is AWSEBDockerrunVersion: 1 - version 1 is the single-container format and it is exactly what you want here:

{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "123456789012.dkr.ecr.us-east-2.amazonaws.com/my-app:latest",
    "Update": "true"
  },
  "Ports": [ { "ContainerPort": 3000 } ]
}

One historical trap worth naming so you avoid it: there used to be a "version 2" multi-container Docker platform built on ECS. AWS has retired it. If you need multiple containers today, that is your signal to go straight to ECS/Fargate rather than force it through Beanstalk. For one container, version 1 is the whole story.

Environment variables the right way

The version 1 file has no field for environment variables, which is the wall most people hit next. You do not want to bake config into the image. Old guides tell you to write a cryptic .ebextensions/*.config file - you can, but there is a far simpler path now.

Just set them from the CLI:

eb setenv DATABASE_URL=postgres://... LOG_LEVEL=info FEATURE_X=true

They land in the environment, survive redeploys, and show up in the console where a teammate can actually find them. If you do prefer config-as-code, the correct .ebextensions form uses a proper namespace rather than the loose key/value that floats around in old posts:

option_settings:
  - namespace: aws:elasticbeanstalk:application:environment
    option_name: LOG_LEVEL
    value: info

For actual secrets - database passwords, API keys - skip both of these and pull them at runtime from AWS Secrets Manager or SSM Parameter Store. Plaintext env vars are fine for config, not for credentials.

Ship it, then redeploy in one command

With your Dockerrun.aws.json and optional .ebextensions/ in place and no Dockerfile in sight, create the environment:

eb create my-app-prod

Beanstalk provisions the instance, pulls your ECR image, wires up health checks, and gives you a URL. From here the loop is delightfully short. Push a new tag to ECR, then:

eb deploy

Because "Update": "true" is set, Beanstalk re-pulls the latest image and rolls it out. No cluster to babysit, no YAML sprawl.

The takeaway

Beanstalk plus ECR is still a legitimately good deploy path for a single containerized service - the docs just aged badly and left a trail of broken commands. Use get-login-password, keep Dockerfile and Dockerrun.aws.json from sharing a directory, stick to version 1 for one container, and set config with eb setenv. Do that and you are live in an afternoon.

We have been shipping containerized apps on AWS since 2016, and the pattern that ages best is the boring one: the fewest moving parts that still meet the requirement. If you are weighing Beanstalk against ECS, App Runner, or something heavier for your own workload and want a second opinion, that is the kind of call we help teams make every week.

enjoyed the read?

LIKE WHAT YOU just read?

Let's talk about what we could build together.