DEV Community

Cover image for From Dockerfile to the Cloud: Deploy a Docker Container on AWS with ECR and ECS Fargate"
Vishal Patil
Vishal Patil

Posted on

From Dockerfile to the Cloud: Deploy a Docker Container on AWS with ECR and ECS Fargate"

description: "A beginner-friendly, step-by-step guide to packaging an app with Docker, storing it in Amazon ECR, and running it on ECS Fargate with no servers to manage."
tags: aws, docker, devops, vishalcloudjourney


Docker is one of the most useful skills for anyone moving into cloud and DevOps. Running a container on your laptop is easy. The real question is how to run it reliably on AWS without managing servers.

In this article, you'll take a simple app from a Dockerfile to a running container on AWS, using these services:

  • Docker to package the app
  • Amazon ECR (Elastic Container Registry) to store the image
  • Amazon ECS with AWS Fargate to run the container with no EC2 instances to manage

What You'll Need

  • An AWS account (a Free Tier account is fine for learning)
  • Docker installed on your machine
  • AWS CLI installed and configured (aws configure)
  • Node.js (optional, only to test the app outside Docker)

Step 1: Create a Simple App

Create a folder called my-docker-app with these files.

app.js

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello from Docker running on AWS Fargate!');
});

app.listen(3000, '0.0.0.0', () => {
  console.log('App running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

package.json

{
  "name": "my-docker-app",
  "version": "1.0.0",
  "main": "app.js",
  "dependencies": {
    "express": "^4.19.2"
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Write the Dockerfile

Dockerfile

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
Enter fullscreen mode Exit fullscreen mode

Why it's written this way:

  • alpine gives you a small image, so pulls are faster and the attack surface is smaller.
  • Copying package*.json first lets Docker cache the dependency layer, so rebuilds are much faster.

Step 3: Build and Test Locally

docker build -t my-docker-app:v1 .
docker run -d -p 3000:3000 my-docker-app:v1
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000. You should see your message. Always test locally first, because it saves a lot of debugging time later.

Tip: If you're on an Apple Silicon Mac, build with --platform linux/amd64 so the image runs on standard Fargate.

Step 4: Push the Image to Amazon ECR

Create the repository:

aws ecr create-repository --repository-name my-docker-app --region ap-south-1
Enter fullscreen mode Exit fullscreen mode

Authenticate Docker to ECR (replace <account-id> with your 12-digit AWS account ID):

aws ecr get-login-password --region ap-south-1 | docker login --username AWS --password-stdin <account-id>.dkr.ecr.ap-south-1.amazonaws.com
Enter fullscreen mode Exit fullscreen mode

Tag and push:

docker tag my-docker-app:v1 <account-id>.dkr.ecr.ap-south-1.amazonaws.com/my-docker-app:v1
docker push <account-id>.dkr.ecr.ap-south-1.amazonaws.com/my-docker-app:v1
Enter fullscreen mode Exit fullscreen mode

Go to ECR → Repositories → my-docker-app in the console. Your image should now be listed.

Step 5: Create an ECS Cluster

  1. Open Amazon ECS → Clusters → Create cluster
  2. Name it docker-demo-cluster
  3. Under infrastructure, keep AWS Fargate (serverless) selected
  4. Click Create

Step 6: Create a Task Definition

A task definition is the blueprint for your container.

  1. Go to ECS → Task definitions → Create new task definition
  2. Name: my-docker-app-task
  3. Launch type: AWS Fargate
  4. CPU / Memory: 0.25 vCPU / 0.5 GB (enough for this demo)
  5. Task execution role: ecsTaskExecutionRole (let ECS create it if it doesn't exist)
  6. Container details:
    • Name: my-docker-app
    • Image URI: <account-id>.dkr.ecr.ap-south-1.amazonaws.com/my-docker-app:v1
    • Container port: 3000
  7. Click Create

The execution role is what allows Fargate to pull your image from ECR and send logs to CloudWatch.

Step 7: Run the Container as a Service

  1. Open your cluster and go to Services → Create
  2. Compute option: Launch type → Fargate
  3. Task definition: my-docker-app-task
  4. Desired tasks: 1
  5. Under Networking:
    • Pick your VPC and a public subnet
    • Create or select a security group that allows inbound TCP 3000 from your IP (or 0.0.0.0/0 for a quick demo only)
    • Turn Public IP on
  6. Click Create

Wait a minute or two until the task status shows Running.

Step 8: Test It

  1. Open Cluster → Tasks → select your running task
  2. Copy the Public IP from the networking section
  3. Visit http://<public-ip>:3000 in your browser

You'll see: Hello from Docker running on AWS Fargate!

Your container is now running on AWS with no servers to patch or manage.

Troubleshooting Common Issues

Problem Likely Cause
Task stops immediately Check the container logs in CloudWatch and confirm the CMD is correct
Can't pull the image The execution role is missing ECR permissions, or the image URI has a typo
Page doesn't load Security group isn't allowing port 3000, or the public IP isn't enabled
"exec format error" Image built for the wrong CPU architecture (see the platform tip in Step 3)

Best Practices

  • Don't use the latest tag in production. Use versioned tags like v1 and v2 so you can roll back.
  • Turn on ECR image scanning to catch known vulnerabilities.
  • Use least-privilege IAM roles for tasks.
  • Put an Application Load Balancer in front for real workloads instead of exposing the task's public IP.
  • Send logs to CloudWatch and set alarms on failures.

Clean Up to Avoid Charges

When you're done:

  1. Set the ECS service desired count to 0, then delete the service
  2. Delete the cluster
  3. Delete the ECR repository (or the image)
  4. Delete any security groups you created for the demo

Conclusion

You've taken an application from source code to a running container on AWS using Docker, ECR, and ECS Fargate. This same pattern scales from a small demo to production workloads. Adding an ALB, auto scaling, and a CI/CD pipeline are natural next steps.

If you found this helpful, let me know which topic you'd like me to cover next.


Author: Vishal Patil

🔗 LinkedIn: vishalpatil-devops-aws
💻 GitHub: VishalPatil-DevOps-AWS

vishalcloudjourney #AWS #Docker #ECS #Fargate #ECR #DevOps #Containers

Top comments (0)