In this article, we'll explore how to provision an AWS Elastic Beanstalk application using Terraform and deploy a containerized React application using GitHub Actions.
Prerequisites
- Terraform CLI installed.
- AWS CLI configured with valid credentials. Refer to this guide for AWS CLI setup.
To verify your AWS credentials, use the following command:
aws sts get-caller-identity
Terraform Configuration
After successfully setting up AWS credentials, let's create the required Terraform scripts.
Define Variables (variables.tf)
We define necessary variables in the variables.tf file as follows:
variable "aws_region" {
description = "The AWS region to deploy resources in"
type = string
default = "us-east-1"
}
variable "application_name" {
description = "The name of the Elastic Beanstalk application"
type = string
default = "react-app"
}
IAM Roles and Profiles (iam.tf)
Elastic Beanstalk requires an EC2 instance profile and a service role. Define these resources in iam.tf
:
resource "aws_iam_role" "eb_ec2_role" {
name = "aws-elasticbeanstalk-ec2-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = { Service = "ec2.amazonaws.com" }
Action = "sts:AssumeRole"
}
]
})
}
resource "aws_iam_instance_profile" "eb_ec2_profile" {
name = "aws-elasticbeanstalk-ec2-profile"
role = aws_iam_role.eb_ec2_role.name
}
resource "aws_iam_role_policy_attachment" "eb_ec2_managed_policy" {
role = aws_iam_role.eb_ec2_role.name
policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier"
}
These resources attach the necessary permissions required by Elastic Beanstalk.
Security Group (sg.tf)
We also need a security group allowing HTTP traffic. Define this in sg.tf
:
resource "aws_security_group" "this" {
name = "react-app-allow-http"
description = "Allow HTTP inbound traffic and all outbound traffic"
vpc_id = data.aws_vpc.default.id
tags = {
Name = "react-app-sg"
}
}
resource "aws_vpc_security_group_ingress_rule" "allow_http" {
security_group_id = aws_security_group.this.id
cidr_ipv4 = "0.0.0.0/0"
from_port = 80
to_port = 80
ip_protocol = "tcp"
}
Elastic Beanstalk Application (ebs.tf)
Define your Elastic Beanstalk application and environment in ebs.tf
:
resource "aws_elastic_beanstalk_application" "this" {
name = var.application_name
description = "This is a React application deployed on AWS Elastic Beanstalk"
}
resource "aws_elastic_beanstalk_environment" "this" {
name = var.environment_name
application = aws_elastic_beanstalk_application.this.name
solution_stack_name = var.solution_stack_name
setting {
namespace = "aws:autoscaling:launchconfiguration"
name = "InstanceType"
value = var.instance_type
}
setting {
namespace = "aws:autoscaling:launchconfiguration"
name = "SecurityGroups"
value = aws_security_group.this.id
}
}
Additional configuration options can be customized within the settings block.
Deploying Terraform Configuration
To provision your resources, execute:
terraform plan
terraform apply
You can define outputs in Terraform to display created resources.
output "ebs_application_name" {
description = "The name of the Elastic Beanstalk application"
value = aws_elastic_beanstalk_application.this.name
}
output "ebs_environment_name" {
description = "The name of the Elastic Beanstalk environment"
value = aws_elastic_beanstalk_environment.this.name
}
Deploying the Application with GitHub Actions
After provisioning resources, set up deployment via GitHub Actions. Add your AWS credentials as secrets (AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) in your repository.
Create a workflow (.github/workflows/deploy.yml):
name: EBS Deployment
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image and run unit tests
run: |
docker image build . -t react-app-dev -f Dockerfile.dev
docker container run -e CI=true react-app-dev npm run test
- name: Generate deployment package
run: zip -r deploy.zip . -x '*.git*'
- name: Deploy to Elastic Beanstalk
uses: einaregilsson/beanstalk-deploy@v22
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: dockerize-react-app
environment_name: react-app-env
version_label: ${{ github.sha }}
region: ${{ secrets.AWS_REGION }}
deployment_package: deploy.zip
use_existing_version_if_available: true
This workflow triggers upon pushing to the main branch, creating a deployment package and deploying your application to Elastic Beanstalk. Adjust this trigger as per your requirements.
Source Code
Thank you for reading
You can find the code at here.
Top comments (1)
Seems crazy! I will definitely try one day :)