Spring Boot with AWS ECS Fargate
Learn how to deploy a Spring Boot application on AWS ECS Fargate step by step using Docker, Amazon ECR, ECS Cluster, Task Definition, Fargate Service, Security Groups, CloudWatch Logs, and production best practices.
Introduction
In the previous article, we deployed a Spring Boot application using AWS Elastic Beanstalk.
Elastic Beanstalk is simple and beginner-friendly, but modern cloud-native applications are commonly deployed as containers.
AWS ECS Fargate allows us to run Docker containers without managing EC2 servers.
With Fargate, AWS manages the infrastructure. We only provide:
- Docker image
- CPU and memory
- Networking
- Environment variables
- Desired number of running tasks
In this article, we will deploy a Spring Boot application on AWS ECS Fargate step by step.
What You Will Learn
- What is Amazon ECS?
- What is AWS Fargate?
- ECS vs EC2 vs Elastic Beanstalk
- How to Dockerize Spring Boot
- How to push Docker image to Amazon ECR
- How to create ECS Cluster
- How to create ECS Task Definition
- How to run Spring Boot on Fargate
- How to configure Security Groups
- How to view CloudWatch logs
- Input and output examples
- Common errors and fixes
- Production best practices
What is Amazon ECS?
Amazon ECS stands for Elastic Container Service.
It is a container orchestration service from AWS.
ECS helps run and manage Docker containers in AWS.
ECS can run containers using two launch types:
| Launch Type | Meaning |
|---|---|
| EC2 | You manage EC2 instances |
| Fargate | AWS manages servers for you |
What is AWS Fargate?
AWS Fargate is a serverless compute engine for containers.
You do not need to manage:
- EC2 instances
- Operating system patches
- Docker runtime installation
- Server scaling
- Cluster capacity
You only define:
- Container image
- CPU
- Memory
- Port
- Environment variables
- IAM roles
- Networking
ECS Fargate Architecture
flowchart TD
DEV[Developer Machine]
APP[Spring Boot Application]
DOCKER[Docker Image]
ECR[Amazon ECR Repository]
ECS[ECS Cluster]
TASK[Task Definition]
FARGATE[Fargate Task]
CW[CloudWatch Logs]
USER[User Browser]
DEV --> APP
APP --> DOCKER
DOCKER --> ECR
ECR --> TASK
TASK --> ECS
ECS --> FARGATE
FARGATE --> CW
USER --> FARGATE
Production ECS Fargate Architecture
flowchart TD
U[Users]
R53[Route 53]
ALB[Application Load Balancer]
ECS[ECS Cluster]
SVC[ECS Service]
T1[Fargate Task 1]
T2[Fargate Task 2]
ECR[Amazon ECR]
RDS[(Amazon RDS)]
CW[CloudWatch Logs]
U --> R53
R53 --> ALB
ALB --> SVC
SVC --> T1
SVC --> T2
ECR --> T1
ECR --> T2
T1 --> RDS
T2 --> RDS
T1 --> CW
T2 --> CW
ECS Important Concepts
| Concept | Meaning |
|---|---|
| Cluster | Logical group for running containers |
| Task Definition | Blueprint for container configuration |
| Task | Running container instance |
| Service | Keeps desired number of tasks running |
| ECR | Docker image registry |
| Fargate | Serverless compute for containers |
| Load Balancer | Routes traffic to running containers |
Prerequisites
Before starting, you need:
AWS Account
AWS CLI
Docker Desktop
Java 17 or Java 21
Maven
Spring Boot Project
IAM permissions for ECS, ECR, CloudWatch, IAM, VPC
Verify Java:
java -version
Output:
openjdk version "17.0.x"
Verify Maven:
mvn -version
Output:
Apache Maven 3.x.x
Verify Docker:
docker --version
Output:
Docker version 25.x.x
Verify AWS CLI:
aws --version
Output:
aws-cli/2.x.x
Step 1: Create Spring Boot Application
Create a Spring Boot project with:
Spring Web
Spring Boot Actuator
Java 17
Maven
Project structure:
springboot-ecs-fargate-demo
┣ src/main/java/com/codewithvenu/ecs
┃ ┣ EcsFargateDemoApplication.java
┃ ┗ controller
┃ ┗ HelloController.java
┣ src/main/resources
┃ ┗ application.yml
┣ Dockerfile
┗ pom.xml
Step 2: Create Main Class
package com.codewithvenu.ecs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EcsFargateDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EcsFargateDemoApplication.class, args);
}
}
Step 3: Create REST Controller
Create file:
src/main/java/com/codewithvenu/ecs/controller/HelloController.java
package com.codewithvenu.ecs.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.Map;
@RestController
public class HelloController {
@Value("${spring.application.name}")
private String appName;
@Value("${app.environment:local}")
private String environment;
@GetMapping("/")
public Map<String, Object> home() {
return Map.of(
"message", "Spring Boot application is running on AWS ECS Fargate",
"application", appName,
"environment", environment,
"timestamp", LocalDateTime.now().toString()
);
}
@GetMapping("/health")
public Map<String, String> health() {
return Map.of("status", "UP");
}
@GetMapping("/version")
public Map<String, String> version() {
return Map.of("version", "1.0.0");
}
}
Step 4: Configure application.yml
Create file:
src/main/resources/application.yml
server:
port: 8080
spring:
application:
name: springboot-ecs-fargate-demo
app:
environment: ${APP_ENVIRONMENT:local}
management:
endpoints:
web:
exposure:
include: health,info
Step 5: Build Spring Boot JAR
Run:
mvn clean package
Output:
BUILD SUCCESS
Generated JAR:
target/springboot-ecs-fargate-demo-0.0.1-SNAPSHOT.jar
Test locally:
java -jar target/springboot-ecs-fargate-demo-0.0.1-SNAPSHOT.jar
Input:
curl http://localhost:8080/
Output:
{
"application": "springboot-ecs-fargate-demo",
"environment": "local",
"message": "Spring Boot application is running on AWS ECS Fargate",
"timestamp": "2026-06-25T10:30:00"
}
Step 6: Create Dockerfile
Create file in project root:
Dockerfile
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/springboot-ecs-fargate-demo-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Step 7: Build Docker Image
Input:
docker build -t springboot-ecs-fargate-demo .
Output:
Successfully built image
Successfully tagged springboot-ecs-fargate-demo:latest
Check image:
docker images
Output:
REPOSITORY TAG IMAGE ID SIZE
springboot-ecs-fargate-demo latest abc123xyz 200MB
Step 8: Run Docker Container Locally
Input:
docker run -p 8080:8080 \
-e APP_ENVIRONMENT=docker-local \
springboot-ecs-fargate-demo
Output:
Tomcat started on port 8080
Started EcsFargateDemoApplication
Test:
curl http://localhost:8080/
Output:
{
"application": "springboot-ecs-fargate-demo",
"environment": "docker-local",
"message": "Spring Boot application is running on AWS ECS Fargate",
"timestamp": "2026-06-25T10:40:00"
}
Stop container:
docker ps
docker stop <container-id>
Step 9: Configure AWS CLI
Run:
aws configure
Input:
AWS Access Key ID: your-access-key
AWS Secret Access Key: your-secret-key
Default region name: us-east-1
Default output format: json
Validate:
aws sts get-caller-identity
Output:
{
"UserId": "AIDAEXAMPLE",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/codewithvenu"
}
Step 10: Create ECR Repository
Amazon ECR is AWS container registry.
Input:
aws ecr create-repository \
--repository-name springboot-ecs-fargate-demo \
--region us-east-1
Output:
{
"repository": {
"repositoryName": "springboot-ecs-fargate-demo",
"repositoryUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo"
}
}
Save repository URI:
123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo
Step 11: Login Docker to ECR
Input:
aws ecr get-login-password --region us-east-1 \
| docker login --username AWS \
--password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
Output:
Login Succeeded
Step 12: Tag Docker Image
Input:
docker tag springboot-ecs-fargate-demo:latest \
123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo:latest
Validate:
docker images
Output:
REPOSITORY TAG
123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo latest
Step 13: Push Image to ECR
Input:
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo:latest
Output:
latest: digest: sha256:abc123 size: 1572
Now the Docker image is available in AWS ECR.
ECR Image Push Flow
flowchart LR
APP[Spring Boot JAR]
IMG[Docker Image]
TAG[Tag Image]
ECR[Amazon ECR]
ECS[ECS Fargate]
APP --> IMG
IMG --> TAG
TAG --> ECR
ECR --> ECS
Deployment Option 1: Deploy ECS Fargate Using AWS Console
Step 14: Create ECS Cluster
Go to:
AWS Console
→ ECS
→ Clusters
→ Create Cluster
Input:
Cluster name: codewithvenu-ecs-cluster
Infrastructure: AWS Fargate
Output:
Cluster created successfully
Step 15: Create Task Execution Role
ECS task execution role allows ECS to pull images from ECR and write logs to CloudWatch.
Role name:
ecsTaskExecutionRole
Required managed policy:
AmazonECSTaskExecutionRolePolicy
This role is commonly created automatically by ECS if not already present.
Step 16: Create Task Definition
Go to:
ECS
→ Task Definitions
→ Create new task definition
Input:
Task definition family: springboot-ecs-fargate-task
Launch type: AWS Fargate
Operating system: Linux/X86_64
CPU: 0.25 vCPU
Memory: 0.5 GB
Task role: None for this demo
Task execution role: ecsTaskExecutionRole
Container input:
Container name: springboot-app
Image URI: 123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo:latest
Container port: 8080
Protocol: TCP
Environment variable:
APP_ENVIRONMENT=ecs-fargate-dev
Logging:
Log driver: awslogs
Log group: /ecs/springboot-ecs-fargate-demo
Region: us-east-1
Stream prefix: ecs
Output:
Task definition created successfully
Step 17: Create Security Group
Create security group for Fargate task.
Inbound rule for learning:
| Type | Port | Source |
|---|---|---|
| Custom TCP | 8080 | 0.0.0.0/0 |
For production, traffic should come through ALB only.
Step 18: Run Task
Go to:
ECS
→ Cluster
→ Tasks
→ Run new task
Input:
Launch type: Fargate
Task definition: springboot-ecs-fargate-task
Cluster: codewithvenu-ecs-cluster
Desired tasks: 1
VPC: default VPC
Subnets: public subnets
Security group: allow 8080
Public IP: Enabled
Output:
Task status: PROVISIONING
Task status: PENDING
Task status: RUNNING
Step 19: Test Running Task
Open ECS task details and copy Public IP.
Input:
curl http://<TASK_PUBLIC_IP>:8080/
Output:
{
"application": "springboot-ecs-fargate-demo",
"environment": "ecs-fargate-dev",
"message": "Spring Boot application is running on AWS ECS Fargate",
"timestamp": "2026-06-25T11:10:00"
}
Health check:
curl http://<TASK_PUBLIC_IP>:8080/health
Output:
{
"status": "UP"
}
Deployment Option 2: ECS Service with Application Load Balancer
Running a task manually is okay for testing.
For production, use ECS Service.
ECS Service keeps the desired number of tasks running.
ECS Service Architecture
flowchart TD
USER[Users]
ALB[Application Load Balancer]
SVC[ECS Service]
T1[Fargate Task 1]
T2[Fargate Task 2]
TG[Target Group]
CW[CloudWatch Logs]
USER --> ALB
ALB --> TG
TG --> SVC
SVC --> T1
SVC --> T2
T1 --> CW
T2 --> CW
Step 20: Create Application Load Balancer
Go to:
EC2
→ Load Balancers
→ Create Load Balancer
→ Application Load Balancer
Input:
Name: springboot-ecs-alb
Scheme: Internet-facing
IP address type: IPv4
VPC: default VPC
Subnets: select at least two public subnets
Security group: allow HTTP 80
Output:
Application Load Balancer created
Step 21: Create Target Group
Input:
Target type: IP addresses
Protocol: HTTP
Port: 8080
VPC: default VPC
Health check path: /health
Output:
Target group created
Important:
For ECS Fargate, target type should be:
IP addresses
not instance.
Step 22: Create ECS Service
Go to:
ECS
→ Cluster
→ Services
→ Create
Input:
Launch type: Fargate
Task definition: springboot-ecs-fargate-task
Service name: springboot-ecs-service
Desired tasks: 2
Networking: public subnets
Security group: task security group
Load balancer: Application Load Balancer
Target group: springboot target group
Container: springboot-app
Container port: 8080
Output:
ECS service created
Desired count: 2
Running count: 2
Step 23: Test ALB URL
Copy ALB DNS name.
Example:
springboot-ecs-alb-123456789.us-east-1.elb.amazonaws.com
Input:
curl http://springboot-ecs-alb-123456789.us-east-1.elb.amazonaws.com/
Output:
{
"application": "springboot-ecs-fargate-demo",
"environment": "ecs-fargate-dev",
"message": "Spring Boot application is running on AWS ECS Fargate",
"timestamp": "2026-06-25T11:30:00"
}
Step 24: View CloudWatch Logs
Go to:
CloudWatch
→ Logs
→ Log groups
→ /ecs/springboot-ecs-fargate-demo
Or use CLI:
aws logs describe-log-groups \
--log-group-name-prefix /ecs/springboot-ecs-fargate-demo
Output:
{
"logGroups": [
{
"logGroupName": "/ecs/springboot-ecs-fargate-demo"
}
]
}
Step 25: Deploy New Version
Update code:
@GetMapping("/version")
public Map<String, String> version() {
return Map.of("version", "1.0.1");
}
Build JAR:
mvn clean package
Build Docker image:
docker build -t springboot-ecs-fargate-demo .
Tag image:
docker tag springboot-ecs-fargate-demo:latest \
123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo:latest
Push image:
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/springboot-ecs-fargate-demo:latest
Force ECS service deployment:
aws ecs update-service \
--cluster codewithvenu-ecs-cluster \
--service springboot-ecs-service \
--force-new-deployment
Output:
{
"service": {
"serviceName": "springboot-ecs-service",
"status": "ACTIVE"
}
}
Test:
curl http://springboot-ecs-alb-123456789.us-east-1.elb.amazonaws.com/version
Output:
{
"version": "1.0.1"
}
ECS Deployment Flow
flowchart LR
CHANGE[Code Change]
BUILD[Build JAR]
IMAGE[Build Docker Image]
PUSH[Push to ECR]
DEPLOY[Force ECS Deployment]
TEST[Test ALB URL]
CHANGE --> BUILD
BUILD --> IMAGE
IMAGE --> PUSH
PUSH --> DEPLOY
DEPLOY --> TEST
Step 26: Environment Variables
You can pass environment variables in Task Definition.
Example:
APP_ENVIRONMENT=prod
SPRING_PROFILES_ACTIVE=prod
DB_HOST=mydb.xxxxxx.us-east-1.rds.amazonaws.com
DB_PORT=5432
Spring Boot config:
spring:
profiles:
active: ${SPRING_PROFILES_ACTIVE:dev}
app:
environment: ${APP_ENVIRONMENT:local}
For secrets, do not use plain environment variables.
Use:
AWS Secrets Manager
AWS Systems Manager Parameter Store
Step 27: IAM Roles in ECS
ECS commonly uses two roles:
| Role | Purpose |
|---|---|
| Task Execution Role | Pull ECR image and write CloudWatch logs |
| Task Role | App permissions to access AWS services |
Example:
If Spring Boot needs to access S3, attach S3 permission to Task Role.
Do not put AWS access keys inside the Docker image.
Common Errors and Fixes
Error 1: Cannot Pull Container Image
Reason:
Task execution role missing ECR permissions
Image URI is wrong
ECR repository is in different region
Fix:
Use ecsTaskExecutionRole
Check ECR image URI
Check AWS region
Error 2: Task Stops Immediately
Check logs:
CloudWatch Logs
→ /ecs/springboot-ecs-fargate-demo
Common reasons:
Application startup failed
Wrong environment variable
Java exception
Port mismatch
Error 3: ALB Shows Unhealthy Targets
Reasons:
Health check path wrong
Security group does not allow ALB to task
Application not listening on expected port
Fix:
Health check path: /health
Container port: 8080
Task security group should allow traffic from ALB security group
Error 4: Public IP Not Working
If running task directly, ensure:
Public IP is enabled
Task is in public subnet
Security group allows port 8080
Route table has internet gateway
Error 5: Docker Build Fails
Run:
mvn clean package
Then:
docker build -t springboot-ecs-fargate-demo .
Make sure the JAR name in Dockerfile matches the actual JAR name.
ECS Fargate Best Practices
- Use Application Load Balancer for production
- Run tasks in private subnets
- Use NAT Gateway for outbound internet access
- Use CloudWatch logs
- Use ECS Service instead of manual tasks
- Configure health checks
- Use minimum two tasks for high availability
- Use IAM Task Role for AWS permissions
- Store secrets in Secrets Manager
- Use CI/CD for image build and deployment
- Use image tags like
1.0.1instead of onlylatest - Enable auto scaling based on CPU or memory
- Monitor cost using AWS Budgets
ECS Fargate vs Elastic Beanstalk
| Feature | Elastic Beanstalk | ECS Fargate |
|---|---|---|
| Deployment model | App platform | Container platform |
| Docker required | Optional | Required |
| Infrastructure control | Medium | Higher |
| Scaling | Built-in | Built-in |
| Microservices | Good | Very good |
| Production container usage | Medium | High |
| Learning curve | Lower | Medium |
ECS Fargate vs EC2
| Feature | EC2 | ECS Fargate |
|---|---|---|
| Server management | Manual | AWS managed |
| Docker installation | Manual | Managed |
| Scaling | Manual/custom | Service auto scaling |
| Deployment | SSH/SCP or pipeline | Container deployment |
| Best for | Learning/custom VM | Cloud-native apps |
Cleanup Resources
To avoid AWS charges, delete unused resources.
Delete ECS service:
aws ecs update-service \
--cluster codewithvenu-ecs-cluster \
--service springboot-ecs-service \
--desired-count 0
Delete service from console:
ECS
→ Cluster
→ Service
→ Delete
Delete ALB:
EC2
→ Load Balancers
→ Delete
Delete target group:
EC2
→ Target Groups
→ Delete
Delete ECR repository:
aws ecr delete-repository \
--repository-name springboot-ecs-fargate-demo \
--force
Delete ECS cluster:
aws ecs delete-cluster \
--cluster codewithvenu-ecs-cluster
Interview Questions
What is ECS?
Amazon ECS is a container orchestration service used to run and manage Docker containers on AWS.
What is Fargate?
AWS Fargate is a serverless compute engine for containers. It allows you to run containers without managing EC2 instances.
What is a Task Definition?
A Task Definition is a blueprint that defines container image, CPU, memory, ports, environment variables, logging, and IAM roles.
What is an ECS Service?
An ECS Service maintains the desired number of running tasks and can integrate with a load balancer.
What is ECR?
Amazon ECR is a container registry used to store Docker images.
Why use ALB with ECS?
Application Load Balancer routes external traffic to ECS tasks and performs health checks.
What is the difference between Task Role and Task Execution Role?
Task Execution Role is used by ECS to pull images and write logs. Task Role is used by the application to access AWS services like S3, SQS, or DynamoDB.
Summary
In this article, we deployed a Spring Boot application on AWS ECS Fargate.
We covered:
- Spring Boot REST API
- Dockerfile creation
- Local Docker testing
- Amazon ECR repository
- Docker image push
- ECS Cluster
- Task Definition
- Fargate Task
- ECS Service
- Application Load Balancer
- CloudWatch logs
- Environment variables
- Common issues
- Production best practices
ECS Fargate is a strong choice for modern cloud-native Java applications because it supports container-based deployment without managing servers.
Comments
Share a question, correction, or practical insight about this article.
Checking login status...
Loading approved comments...