This repository contains a Spring Boot application that is automatically deployed to AWS Fargate using GitHub Actions and Terraform for infrastructure as code.
The application is deployed using the following AWS services:
- Amazon ECR: Stores the containerized application
- AWS Fargate: Runs the containers without server management
- Amazon ECS: Orchestrates the containers
- Application Load Balancer: Routes traffic to the application
- VPC with public and private subnets: Provides networking isolation
- CloudWatch Logs: Collects application logs
├── .github/
│ └── workflows/
│ └── deploy.yml # GitHub Actions workflow for CI/CD
├── terraform/
│ ├── main.tf # Main Terraform configuration
│ ├── variables.tf # Variable definitions
│ ├── outputs.tf # Output definitions
│ └── backend.tf # Terraform state configuration
├── src/ # Spring Boot application source code
├── Dockerfile # Docker image definition
├── .dockerignore # Files to exclude from Docker builds
├── build.gradle # Gradle build configuration
├── settings.gradle # Gradle settings
└── README.md # This file
NOTE: Before doing any changes to this repository, fork it first!
- AWS Account with appropriate permissions
- AWS credentials stored as GitHub secrets
Before you can deploy your Spring Boot application to AWS using Terraform and GitHub Actions, you need to complete several prerequisite steps. This guide walks you through setting up all required resources and permissions.
- AWS v2 CLI - https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions
- Git CLI
- Go to AWS Console
- Click "Create an AWS Account" and follow the registration process
- Set up Multi-Factor Authentication (MFA) for the root account for security
- Apply Voucher - steps TODO
- Log in to AWS Console with your root account
- Go to your account name in the top right corner → "My Account"
- Scroll to "Billing preferences" and check:
- "Receive Billing Alerts"
- "Receive PDF Invoice By Email"
- Click "Save preferences"
Recommended to use for everything (except billing) instead of your root user.
Assign to new group: admins.
Set permission AdministratorAccess to group.
Perform everything via this user.
-
Log in to AWS Console
-
Navigate to IAM (Identity and Access Management)
-
Create a new IAM user:
Name: terraform-deployer Access type: Programmatic access Group: iac -
Attach the following policies to group iac:
AmazonECS_FullAccessAmazonEC2ContainerRegistryFullAccessAmazonVPCFullAccessAmazonS3FullAccess(for Terraform state)AmazonSNSFullAccess(for billing alarms)CloudWatchFullAccessIAMFullAccessElasticLoadBalancingFullAccess
-
After creating the user, save the Access Key ID and Secret Access Key securely in GitHub and also download csv file with them.
# Login to AWS account using your ACCESS_KEY_ID and SECRET_KEY
aws configure
# Create S3 bucket for Terraform state
aws s3api create-bucket \
--bucket terraform-state-spring-boot-app \
--region us-east-1
# Enable bucket versioning
aws s3api put-bucket-versioning \
--bucket terraform-state-spring-boot-app \
--versioning-configuration Status=Enabled
# Enable default encryption
aws s3api put-bucket-encryption \
--bucket terraform-state-spring-boot-app \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
}'- Go to GitHub
- Click "New" to create a new repository
- Give it a name and description, choose visibility options
- Initialize with a README if desired
- Click "Create repository"
- Go to your repository on GitHub
- Click on "Settings" → "Secrets and variables" → "Actions"
- Add the following secrets:
AWS_ACCESS_KEY_ID: Your IAM user's access keyAWS_SECRET_ACCESS_KEY: Your IAM user's secret keyAWS_REGION: Your preferred AWS region (e.g.,us-east-1)
- Click on the "Actions" tab in your repository
- Confirm that you want to enable GitHub Actions
# Clone your repository
git clone https://github.com/yourusername/your-repo-name.git
cd your-repo-name
# Create necessary directories
mkdir -p .github/workflows
mkdir -p terraform
# Copy all the provided files from this guide into these directories
# (Terraform configs, GitHub Actions workflow, Docker file, etc.)
# Update variables.tf with your specific values
# - Update the AMI ID
# - Update the alarm email
# - Adjust any other variables as needed
# Commit and push your changes
git add .
git commit -m "Add deployment configuration"
git push origin mainEnsure your Spring Boot application:
- Has proper health checks at
/actuator/health - Uses environment variables for configuration
- Can run as a non-root user (for security)
- Has proper logging configuration
Add these dependencies to your build.gradle:
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'- Push your code to the main branch
- Go to the "Actions" tab in your GitHub repository and trigger "Deploy Spring Boot App" action
- Watch as your first deployment runs
- Troubleshoot any issues by checking the workflow logs
After deployment, verify:
- The application is running by visiting the ALB DNS name
- Logs are being properly sent to CloudWatch
- The billing alarm is properly configured
- You received an email to confirm the SNS subscription for billing alerts
To avoid incurring any costs, you can destroy all resources when they're no longer needed:
cd terraform
terraform destroyor you can trigger GitHub action called Terraform destroy manually, which will do the same thing.
Review and update:
- Environment variables in
.github/workflows/deploy.yml - Default values in
terraform/variables.tf
The CI/CD pipeline runs automatically when code is pushed to the main branch:
-
Infrastructure Provisioning:
- Terraform creates or updates AWS resources
-
Application Build:
- Java application is built with Gradle
- Docker image is created
-
Container Publishing:
- Image is pushed to Amazon ECR
-
Deployment:
- ECS task definition is updated
- New containers are deployed to Fargate
- Old containers are decommissioned
- CloudWatch: Application logs are sent to CloudWatch
- Health Checks: Spring Boot actuator health endpoints are used for container health monitoring
Open in your browser:
http://localhost:8080/swagger-ui/index.html
Execute in your terminal:
curl -X 'GET' \
'http://localhost:8080/rest/app/demo/v1/{name}?name=Marian' \
-H 'accept: application/json'
./gradlew builddocker build -t spring-boot-app .
docker run -p 8080:8080 spring-boot-app

