Mastering App Deployment on AWS: Step-by-Step with ECR, EC2, ECS, Fargate & Load Balancer

Table of contents

🌟 Introduction

Have you ever built an application that worked perfectly on your laptop, only to watch it break during deployment? You’re not alone. This "it works on my machine" problem is exactly what containerization with Docker solves.

In this comprehensive guide, I’ll walk you through how I deployed my Veget Foods website on AWS. We’ll containerize the app with Docker, store the image in Amazon Elastic Container Registry (ECR), and deploy it using Elastic Container Service (ECS). We'll compare both launch types: EC2 (for control) and Fargate (for serverless simplicity). Finally, we'll put everything behind an Application Load Balancer (ALB) for scalability and high availability.

By the end, you'll have a fully functional, cloud-native deployment pipeline and a clear understanding of how these core AWS services work together.

🐳 Step 1: Containerize the Application with Docker

First, we need to package our app. Here’s a basic Dockerfile for a Node.js app (adapt this for your tech stack):

dockerfile

# Use an official runtime as a base image
FROM node:18-alpine

# Set the working directory
WORKDIR /app

# Copy package files and install dependencies
COPY package*.json ./
RUN npm ci --only=production

# Copy application source code
COPY . .

# Expose the port the app runs on
EXPOSE 3000

# Define the command to run the app
CMD ["node", "app.js"]

Build and test the image locally:

bash

docker build -t veget-foods-app .
docker run -p 3000:3000 veget-foods-app

Visit http://localhost:3000 to confirm it works before moving to the cloud.

📦 Step 2: Store the Image in Amazon ECR (Elastic Container Registry)

ECR is AWS's private Docker registry, seamlessly integrated with IAM and ECS.

  1. Create a Repository: In the AWS Console, navigate to ECR and create a new private repository (e.g., veget-foods-app).

  2. Authenticate & Push: Use the AWS CLI to authenticate Docker and push your image. The commands provided in the console are your best friend here.

bash

# Authenticate your Docker client to your ECR registry
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

# Tag your local image for ECR
docker tag veget-foods-app:latest YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/veget-foods-app:latest

# Push the image
docker push YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/veget-foods-app:latest

Image ✅ in ECR!

⚙️ Step 3: Create the ECS Task Definition

The task definition is the blueprint for your application. It tells ECS how to run your container.

  • Key settings: CPU, Memory, and the container definition (pointing to your ECR image URI).

  • Crucial Step: You must create an Execution Role that grants ECS permission to pull the image from ECR. This is a common stumbling block.

  • Choose Launch Type: You'll create two definitions or decide here: one for EC2 and one for Fargate. The main difference in the definition is the requiresCompatibilities field.

🌐 Step 4: Configure the ECS Cluster and Service

  1. Cluster:

    • For EC2: Create a cluster and add EC2 instances to it (or use an Auto Scaling group).

    • For Fargate: You can use the default "FARGATE" cluster or create a new one. No servers to manage!

  2. Service: This is what runs and maintains your tasks.

    • Key Step: When creating the service, you configure the Load Balancer. You need to:

      • Create a Target Group.

      • Map your container's port (e.g., 3000) to the load balancer.

    • The service ensures the desired number of tasks are always running and registers them with the ALB.

✅ Step 5: Test Your Live Deployment

Once the service is created, ECS begins launching tasks. After a few minutes, the ALB will perform health checks.

  1. Go to the EC2 console > Load Balancers.

  2. Find your ALB and copy its DNS Name.

  3. Paste it into your browser. Your containerized application should now be live on the internet! 🎉

📖 Frequently Asked Questions (FAQ)

Q1: What’s the real-world cost difference between ECS on EC2 vs. Fargate?
A: EC2 can be cheaper for predictable, long-running workloads where you can maximize utilization. Fargate is often more expensive per hour but has no idle cost; you only pay for the time your task is running. It simplifies cost forecasting for variable traffic.

Q2: Why did my ECS task fail to start?
A: The most common reasons are: 1) The ECS Execution Role is missing permissions to pull from ECR, 2) The Docker container exits immediately due to an error (check CloudWatch logs!), or 3) A security group is blocking traffic.

Q3: When would I not want to use a Load Balancer with ECS?
A: Skip the ALB for internal backend services (e.g., a worker processing a queue) or for tasks that don't need to accept inbound network requests.

🎯 Conclusion

Deploying an app with Docker on AWS might seem complex, but by breaking it down into managed services (ECR, ECS, Fargate, ALB), it becomes a powerful and repeatable pattern.

This deployment pipeline for the Veget Foods website taught me that while ECS on EC2 offers more control for deep customization, Fargate's serverless nature dramatically reduces operational overhead, letting me focus purely on the application code.

Now I'm curious: which launch type fits your needs better? Are you team "I need full control" (EC2) or team "I hate managing servers" (Fargate)? Let me know your thoughts in the comments! 👇

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.