Deploy in AWS using Terraform. Deploy your dockerized react…
By: Kvs Sankar
Tags: React, Mern, AWS, Docker, Terraform

Deploy your dockerized react application in AWS using terraform

Before starting let me tell you that this is a part of my series “Making your React app hosting ready”. In the series, I explained how to convert your react app to a progressive web app, implement server-side rendering and dockerize the application and make it ready for hosting it in AWS using Terraform. Do check it out 😉

BTW you need to create an AWS account with your credit or debit card credentials in order to proceed. This is just for account creation I assure you, you won't be charged any money, we will be using only free tiers 🙂

Disclaimer: Don't forget to destroy everything in aws after the work is done or else you will charged.

Now before entering, what is Terraform?

Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently

I nfrastructure as code

Basically, instead of manually handling your AWS services, instances, and all, we write the whole thing as a code which helps us to maintain everything efficiently. Even if there are any updates or version changes we can make sure everything is working fine.

You need to know some things in order to be on the same page:

AWS or at least knowledge on any cloud infrastructure Basics of Terraform (Even though we copy the whole codes from documentation 😂) Install terraform cli. Follow this youtube link to install terraform in windows.

Create a main.tf file and run the below command in the working directory (where you created main.tf file) to initialize terraform:

terraform init

Workflow:

Configure AWS provider Generate AWS key pair for ssh into the instance Create default vpc Create default subnet Create a security group to allow HTTP, HTTPS, ssh traffic (basically making our server available to all users) Create aws instance SSH into instance Install docker Run your Docker image

Configure AWS provider

AWS console -> my security credentials -> access keys

Generate a key pair and save it somewhere locally or else you need to generate a new one if you miss it 🥱.

terraform {

required_providers {

aws = {

source = "hashicorp/aws"

version = "~> 3.0"

}

}

} provider "aws" {

region = "us-east-1"

access_key = "...................."

secret_key = "....................."

}

You don't need to memorize all these 🤓, since the documentation of terraform is top-notch 🤩. You will find all the sample codes, just search in google terraform aws configure, or terraform aws default subnet anything you need is perfectly available. So all you need to do is understand how everything is working and have knowledge of any of the cloud infrastructure.

If you need any kind of help let me know in the comments 🧐

Generate Keypair for instance

Method-1:

You can do it manually since we need it only while initializing. One can find it in aws console -> ec2 -> network and security -> key pairs

Download the key pair in your working directory and leave it as of now, we will get back to it later

Method-2:

resource "tls_private_key" "key" {

algorithm = "RSA"

rsa_bits = "4096"

} resource "aws_key_pair" "generated_key" {

key_name = "main"

public_key = tls_private_key.key.public_key_openssh } resource "local_file" "key_file" {

content = tls_private_key.key.private_key_pem

filename = "main.pem"

file_permission = 0400

}

We generate a tls private key and use it for aws key pair. TLS private key is the standard way to create a public and private key. Later we use local file resource and download it locally in the working directory.

Create default vpc:

resource "aws_default_vpc" "default" {

tags = {

Name = "Default VPC"

}

}

Using aws_default_vpc resource we create a default vpc

Create a default subnet:

resource "aws_default_subnet" "default_az1" {

availability_zone = "us-east-1a"

tags = {

Name = "Default subnet for ap-south-1a"

}

}

Using aws_default_subnet resource we create a default subnet

Create a security group:

resource "aws_security_group" "sg1" {

vpc_id = aws_default_vpc.default.id

name = "allow_ssh_http" lifecycle {

create_before_destroy = true

} ingress {

from_port = 22

to_port = 22

protocol = "tcp"

cidr_blocks = ["0.0.0.0/0"]

} ingress {

from_port = 80

to_port = 80

protocol = "tcp"

cidr_blocks = ["0.0.0.0/0"]

}

egress {

from_port = 0

to_port = 0

protocol = "-1"

cidr_blocks = ["0.0.0.0/0"]

} }

We create a security group to allow HTTP, ssh traffic. The default port for HTTP is 80, ssh is 22 and HTTPS is 443. In ingress, we basically tell which ports we are allowing and the protocol for it.

Know more about TCP protocol here.

In egress protocol = -1 says allowing all protocols.

Create instance

resource "aws_instance" "ui_instance" {

ami = "ami-0be2609ba883822ec"

instance_type = "t2.micro"

availability_zone = "us-east-1a"

key_name = aws_key_pair.generated_key.key_name

subnet_id = aws_default_subnet.default_az1.id

vpc_security_group_ids = [aws_security_group.sg1.id]

connection {

type = "ssh"

user = "ec2-user"

host = aws_instance.ui_instance.public_ip

private_key = tls_private_key.key.private_key_pem

timeout = "10m"

} provisioner "remote-exec" {

inline = [

"sudo yum update -y",

"sudo amazon-linux-extras install docker -y",

"sudo usermod -a -G docker ec2-user",

"sudo service docker start",

"sudo docker pull <username>/<image-name>",

"sudo docker container run -d -p 80:80 <username>/<imagename>"

]

}

tags = {

Name = "production"

}

}

We need an AMI (Amazon machine image), which is basically an id for different operating systems. Here I used amazon Linux 2 of t2.micro type which is free.

We need to mention the vpc id, subnet id, availability zone, and the key name.

Keyname we will get it from the resource aws_key_pair.genrated_key.key_name as mentioned in the docs again 😉.

After launching the ec2 instance, we used a connection block to ssh into our instance.

Terraform provides provisioners for running os specific commands. There are two types of provisioners.

local-exec remote-exec

We use the “local-exec” provisioner to run commands on our localhost. We use “remote-exec” to run commands on our remote host.

In the above code, we used the “remote-exec” provisioner to run commands for installing docker and pulling the image, and running it in a detached state.

You can check the above code for those commands we again you can find in AWS ec2 docker configuration docs or if you're a Linux user you will know it.

Run the below code to see what all are going to be created in your AWS account:

terraform plan

After you are sure with everything run :

terraform apply

This will create all the instances, subnets, vpc, security groups which you can check in your console.

Click on the public IP to visit your website.

Looks like my work is done here. If you have any doubts feel free to comment or reach me here 😃

In my next article I will go deep into terraform-aws how to create :

Virtual Private Cloud Subnets Route Table Internet Gateway Security Groups

Do consider applauding my article and following me for more such awesome content 🤩🤩🤩