Containerizing Your App with AWS ECR, EC2, ECS, Fargate & Load Balancer: A Step-by-Step Guide:

My DevOps First Win!

Hey hey DevOps fam! 👋🏾
Let me gist you about how I brought my little frozen food website — Veget Foods — to life using Docker and AWS.
This was my first ECS (EC2 launch type) deployment and guess what? I did it manually, step-by-step, like a real DevOps engineer. 😎

“Containers don’t have to be complicated — especially on AWS.”

If you’ve ever wanted to deploy a containerized application on AWS without battling Kubernetes complexity, you’re in the right place.
In this guide, I’ll walk you through building, pushing, and running your app using Amazon ECS with the EC2 launch type, plus an Application Load Balancer for smooth, high-availability access.

We’ll cover everything step-by-step so you can follow along — whether you’re a DevOps newbie or just exploring AWS container services.

If you’re on the DevOps learning path like me and want to see what deploying a real website looks like, this post is for you.


🧾 The Backstory

I had this simple HTML site for Veget Foods, my frozen food brand. Nothing fancy, just a welcome message. But I wanted more than just viewing it locally.

I wanted to:
✅ Package it in a Docker container
✅ Push it to ECR
✅ Run it on ECS (EC2 launch type)
✅ Set up a Load Balancer (ALB)
✅ And of course… show it off publicly 😁

So, I rolled up my sleeves and went all in. Let me walk you through how I did it — mistakes, wins, and lessons included.

🌟 Why ECS Over EKS?

AWS gives you two main container orchestration options:

  • ECS (Elastic Container Service) – Perfect if you want a fully managed, straightforward solution without having to manage Kubernetes yourself.

  • EKS (Elastic Kubernetes Service) – Ideal if you need the flexibility and complexity of Kubernetes.

For this project, I went with ECS (EC2 launch type) — meaning I managed the EC2 instances myself but still let ECS handle container orchestration.


🧩 AWS ECS in a Nutshell

Think of ECS as AWS’s brain for managing your containers. It:

  • Runs and scales Docker containers across multiple Availability Zones

  • Works with EC2 (you manage servers) or Fargate (AWS manages servers for you)

  • Integrates with IAM, VPC, CloudWatch, ECR, CodePipeline, and Load Balancers

  • Offers auto-scaling out of the box


🏗 ECS Building Blocks

Here’s what makes up an ECS deployment:

  • Cluster → A logical group where your containers run

  • Task Definition → The blueprint for your app (image, CPU, memory, networking, etc.)

  • Tasks → Running instances of your Task Definition

  • Service → Ensures the desired number of tasks are running and restarts failed ones

  • Container Instances → EC2 machines or serverless Fargate tasks where containers live


🛠 What We’ll Do in This Project

We’re going to:

  1. Containerize our application

  2. Push our image to Elastic Container Registry (ECR)

  3. Create an ECS Cluster with Task Definitions and Services

  4. Set up IAM Roles and Security Groups

  5. Deploy with an Application Load Balancer (ALB)

By the end, you’ll be able to hit your app’s DNS name and see it live.


🧰 Tools I Used

  • Docker – for containerizing the app

  • Amazon ECR – to store the Docker image

  • Amazon ECS (EC2) – to run the containers

  • EC2 Instance – compute power

  • Application Load Balancer (ALB) – for public access and traffic routing

  • Target Group – for directing traffic to tasks


🛠️ Step-by-Step Deployment

🚀 Step 1: Spin Up an EC2 Instance

  1. Create an EC2 instance. (See AWS EC2 Instance Launch if you need help.)

  2. Under Network Settings, create a new Security Group and add an HTTP inbound rule (Type: HTTP, Source: 0.0.0.0/0).

  • Launch your instance.

🔑 Step 2: Connect to EC2

You can connect via:

  • Instance Connect (browser-based terminal)

  • SSH Client (requires your EC2 key pair)

For SSH:

ssh -i "your-key.pem" ec2-user@<your-ec2-public-ip>
sudo su
yum update -y
  • Then: enter root and update: sudo su , yum update -y . The sudo su command takes you to the root user and yum update -y, updates your Amazon Linux.

🐳 Step 3: Install Docker

To install docker, you have to run the following commands. curl -fsSL https://get.docker.com -o get-docker.sh, yum install docker -y, systemctl start docker

After successfully installing docker, we use the systemctl start docker to start docker, then run systemctl status docker to know the status of docker. From the diagram below, you would realize that docker is started, active and running.

To continue with your commands, type Q and it takes you to the root folder again.

Create a project directory:

mkdir veget_foods && cd veget_foods

📂 Step 4: Build App & Dockerfile

b. Type vi dockerfile to create dockerfile and input the code below

Here is my Dockerfile:

Type vi Index.html to create your html file. Put in your code, save and exit.

Login to your docker account by typing docker login and inputting all the necessary information. :docker login

📂 Step 5: Build the Docker Image

Run the command docker build -t veget-foods . to build the docker image

🗝 Step 6: Configure AWS CLI

  1. In AWS Console: IAM → Users → Create Access Keys (for CLI use).

  2. Select CLI as your use case.

  3. Select confirmation box - Next - Create access keys.

After creating the access keys, navigate back to the terminal and type aws configure , Enter your Access Key, Secret Key, region, and output format when prompted

🏷 Step 7: Create ECR Repository

aws ecr create-repository --repository-name veget-repo

Copy the repository URI from the AWS Console.

After creating the repository, you can confirm on AWS Console. Click on the repository that has just been created. Next, click View Push Commands and a dialog box would be opened.

Step 8: Push to Amazon ECR

Logged into ECR: Run these commands on the terminal to tag and push your image to Amazon ECR.

aws ecr get-login-password | docker login --username AWS --password-stdin <your-ecr-url>

Tagged the image:

docker tag veget-repo:latest <your-ecr-url>/veget-repo:latest

Then pushed it:

docker push <your-ecr-url>/veget-repo:latest

Image ✅ in ECR!

🖥 Step 9: Create ECS Cluster & Task Definition

  1. ECS Console → Create Cluster → EC2 Linux + Networking

  2. Name it veget-cluster (or another unique name).

  3. Under Task Definitions → Create New:

    • Name: veget_task_dev

    • Launch type: EC2

    • Container name: veget-container

    • Image: Your ECR image URI

    • Port mapping: 80 → 80Create a container to run Your image by running the command in the diagram below.

# run the container in the background, map host port 80 -> container port 80
docker run -d --name veget-container -p 80:80 veget-foods

# check running containers
docker ps

ECS Cluster Setup (EC2 Launch Type)

Inside the ECS Console:

  • Created a cluster using "EC2 Linux + Networking"

  • Named it veget-cluster

  • Chose t2.micro for testing (Free Tier friendly)

  • Selected my key pair and default VPC/subnets

Under ECS > Task Definitions:

  • Name: veget_task_dev

  • Launch type: EC2

  • Container name: veget-container

  • Image: My ECR image URL

  • Port mapping: Container 80 → Host 80

Saved and registered it

⚖ Step 10: Set Up Load Balancer

  1. Go to EC2 → Load Balancers → Create.

  2. Name: veget-alb, Scheme: Internet-facing, Listener: Port 80.

b. Give your load balancer a name,ensure it is internet facing. Leave the other parts as default and move to Network mapping.

c. Under Network mapping, select the VPC. In my case, it was the default VPC and I selected 2 AZs which automatically attached the subnets.

d. Under Security groups, click on the drop down arrow and select the security group you created when creating the EC2.

e. Under Listeners and routing, select Create Target group.

  1. Create Target Group:

    • Type: IP

    • Protocol: HTTP, Port: 80

    • Health check path: /index.html : This helps ALB know if your app is healthy or not.

  2. Attach Target Group to the ALB

Give the Target group a name.

Move to Advanced health check settings and scroll to Healthy threshold.

Click Next

Select your instance, next select Create Target group.

Return to Listener and routing so that you can add the load balancer.

Now create the load balancer:

Now the juicy part — making the site public!

  • Created a new ALB

  • Name: veget-alb

  • Scheme: Internet-facing

  • Listener: Port 80

Waited a bit for provisioning...

🛡 Step 11: Create an ECS Task Role

In IAM → Roles:

  • Select AWS Service.

  • Choose Elastic Container Service.

  • Attach relevant policies.

Checking for role created

🚀 Step 12: Deploy Service

In ECS Console: Create ECS Resources

  1. Go to ECS → Task Definitions → Create New.

  2. Use the Task Role you just made.

  3. Add a container pointing to your ECR image.

  4. Create a Cluster.

  5. Create a Service in that cluster:

    • Select your Task Definition.

    • Desired tasks: 2.

    • Enable Load Balancing.

Back in ECS > Clusters > veget-cluster > Services:

  • Launch type: EC2

  • Task def: veget_task_dev

  • Service name: veget_task_dev-service

  • Tasks: 2

  • Attached to the Load Balancer

Selected the right listener

Selected the right target group

Hit create… and crossed my fingers 🤞🏾

✅ Step 13: Test Your Deployment

Grab your ALB DNS name, paste it in your browser… and there’s your app 🎉

If it doesn’t work, check:

  • Target Group health

  • Security Group inbound rules

It Worked!! 🎉

Visited the ALB DNS name, and boom 💥 — my Veget Foods website was live on the internet. Just like that!

😵 What Went Wrong?

Oh, trust me — it wasn’t all smooth. Here are a few hiccups:

❌ “Circuit breaker triggered”

This scared me at first, but it just meant the container didn’t pass the health check. I had forgotten to update the health check path in the target group to /index.html.

❌ Target group was empty

Make sure you use IP as the target type and that the tasks actually start and run correctly on EC2.

❌ Website not loading?

Check your security group and open port 80 to 0.0.0.0/0.

I had to tear everything down and start afresh — delete task definitions, target groups, load balancer, and all. But that’s part of learning! 💪🏾


🧠 Key Lessons I Learned

  • ECS (EC2) is a great way to learn container orchestration manually.

  • ALB and Target Groups need to be properly configured for your service to be reachable.

  • Don’t panic when stuff breaks. Delete. Rebuild. Learn. 🔁


📸 Here's Proof

Look at that screen! My site, running from a container, on ECS, behind an ALB. Proud DevOps moment. ❤️‍🔥


🎯 Final Words

Deploying the Veget Foods website using Docker, Amazon ECS (EC2), and an Application Load Balancer was a rewarding journey that provided valuable insights into container orchestration and cloud deployment. This hands-on experience highlighted the importance of meticulous configuration, especially with ALB and Target Groups, to ensure seamless access to the application.
Despite encountering challenges like health check failures and security group misconfigurations, the process reinforced the value of persistence and iterative learning.
This project not only boosted my confidence in handling real-world DevOps tasks but also underscored the potential of ECS as a powerful tool for managing containerized applications. For anyone on a similar learning path, embracing the trial-and-error process is key to mastering these technologies.
So if you’re also learning DevOps, don’t be scared of ECS — dive in, break things, fix them, and deploy your own project!

Have any questions, or trying this yourself? Drop your comments — I’m happy to help!

Until the next deployment,
Betty Musari 💜

0
Subscribe to my newsletter

Read articles from Funmilola Elizabeth Opeyemi Musari directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Funmilola Elizabeth Opeyemi Musari
Funmilola Elizabeth Opeyemi Musari

👋 Hi, I’m Betty Musari — a former food scientist now diving deep into the world of DevOps and cloud engineering. I write about my hands-on journey with AWS, Docker, and CI/CD, translating complex concepts into clear, beginner-friendly stories. With a scientific mindset and a passion for continuous learning, I'm on a mission to demystify the cloud — one container at a time. ✨As a Food Technologist & Sales Strategist turned DevOps Explorer, I leverage problem-solving and client-centric skills to build resilient cloud systems. Currently mastering CI/CD pipelines, Azure, and Infrastructure as Code (Terraform) to automate deployments like a well-oiled production line. Passionate about merging operational efficiency with technical innovation—because great systems, like great recipes, require precision and scalability.