Create CI/CD with Github Actions + AWS EC2, CodeDeploy and S3
By: Suparerk Yodcharoen
Tags: AWS, Web Development, Continuous Delivery, Continuous Integration, DevOps

Let’s get started!

1. Create IAM Role for EC2 instance & CodeDeploy

From AWS Console, navigate to Identity and Access Management (IAM) .

. Select Access management then Role .

then Select Create role .

Create Role for EC2 instance

T his role will allow EC2 to communicates with CodeDeploy

Select EC2 as a use case, then click Next: Permission

From search box, searching for AmazonEC2RoleforAWSCodeDeploy and select it.

then searching for AutoScalingNotificationAccessRole and select it.

click Next: Tags Give it a tags you desire or you can leave it blank and click Next: Review

Give it a tags you desire or you can leave it blank and click Give it a name CodeDeployInstanceRole or any name you want.

Create Role for CodeDeploy

T his role will allow CodeDeploy to communicates with EC2,

From create role screen, scroll down and select CodeDeploy as a use case, then click Next: Permission

You’ll see it’s already add required permission for us. click Next: Tags

Give it a tags you desire or you can leave it blank and click Next: Review

Give it a name CodeDeployServiceRole or any name you want.

Now we have CodeDeployInstanceRole and CodeDeployServiceRole .

2. Launch EC2 Instance for our application

From AWS Console, navigate to EC2 . and click Launch Instance

In this article i’ll use Ubuntu Server 18.04 LTS as a machine image.

Search for Ubuntu then click Select on Ubuntu Server 18.04 LTS

Select your desire instance type (t2.micro would be enough for a small application) and then click Next: Configure Instance Details .

. Looking for IAM role and select CodeDeployInstanceRole . Role that we just created.

Scroll down and looking for User data , copy and paste script below.

FROM SCRIPT BELOW, YOU’LL HAVE TO…

Replace bucket-name and region-identifier with your region. For a list of bucket names and region identifiers, see Resource Kit Bucket Names by Region. For example if you’re using ap-southeast-1 (Singapore) this line of code will be wget https://aws-codedeploy-ap-southeast-1.s3.ap-southeast-1.amazonaws.com/latest/install



sudo apt-get update

sudo apt-get install ruby

sudo apt-get install wget

cd /home/ubuntu

wget

chmod +x ./install

sudo ./install auto

sudo service codedeploy-agent start #!/bin/bashsudo apt-get updatesudo apt-get install rubysudo apt-get install wgetcd /home/ubuntuwget https:// bucket-name .s3. region-identifier .amazonaws.com/latest/install chmod +x ./installsudo ./install autosudo service codedeploy-agent start curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -

sudo apt-get install -y nodejs sudo npm install pm2 -g

T his script will install CodeDeploy Agent, NodeJS and PM2 on our instance in launch time.

Click Next: Add Storage and give your desire storage size

and give your desire storage size Click Next: Add Tags you need to add tags for CodeDeploy to identify which is what.

example, if you have two instance running the same project but one instance is for production and another one for staging, you may add tags that define which instance is what such as env=staging name=aws-codedeploy

Click Next: Configure Security Group . We’ll run our application on port 3000, we have to add HTTP and TCP Port 3000 to security group so we can access this port from outside world.

Y ou may setup nginx for reverse proxy and remove unwanted rule later.

Click Review and Launch

Now we have EC2 Instance running and ready for deployment.

3. Create S3 bucket for our application revision

This bucket will store our application in CodeDeploy process before deploy to EC2

From AWS Console, navigate to S3 , then click Create bucket

, then click Give it a name aws-codedeploy-deployments or any name you like and don’t for get to select Block all public access this is important. click Create bucket

Now we have our deployments bucket that will store application revision. Let’s move to our code.

4. Setup our project for CodeDeploy, PM2 and Github Workflows

You’ll have to create following files

./ecosystem.config.js

./appspec.yml

./scripts/reload-pm2.sh

./.github/workflows/ci-cd.yml

Let’s start with ecosystem.config.js

Create ecosystem.config.js at your root folder

We’ll serve our application with serve on port 3000

Next, appspec.yml

Create appspec.yml at your root folder.

Keep in mind that All keys/properties and indent are case-sensitive for YAML file.

This AppSpec file tells CodeDeploy where to get source and where to deploy with permission of who.

Hooks will run during lifecycle event of deployment. Each hook is executed once per deployment.

See AppSpec Reference and Hooks Reference for more information.

Next, reload-pm2.sh script

Create reload-pm2.sh at ./scripts

This script will run on ApplicationStart that we have declare above in appspec.yml this will start reload our pm2 process automatically.

Create ci-cd.yml at ./.github/workflows/

You may change appname deploy-group s3-bucket and s3-filename to match your configuration

This workflows will running on push and pull request in staging branch

If test succeeds it will start to build and deploy our app using AWS CLI

In AWS Deploy push step. it will upload our project to S3 bucket.

In AWS Create Deployment step. It create deployment in CodeDeploy to deploy our app.

Now let’s move to AWS Console and setup our CodeDeploy

5. Setup CodeDeploy

From AWS Console, navigate to CodeDeploy then Applications

then Click Create application , give it a name and choose EC2/On-premises and click Create application

inside our application click Create deployment group give it a name (in this case we name it after our stage that is staging ). Select role CodeDeployServiceRole that we just created above.

In Development type. select In-place just for development but in a real world you may choose Blue/green and setup EC2 Auto Scaling group (you don’t want your app to be down right?).

just for development but in a real world you may choose Blue/green and setup EC2 Auto Scaling group (you don’t want your app to be down right?). In Environment configuration. select Amazon EC2 instances and type tags that you defined when you launch instance, CodeDeploy will identify it automatically

In Deployment settings. select CodeDeployDefault.OneAtATime

In Load balancer. deselect Enable load balancing and click Create deployment group

Now we’re almost ready Let’s create IAM account for our Github.

6. Create IAM account

From AWS Console, navigate to IAM and User and click Add user . select Programmatic access then click Next: Permission

Add this two permission to this user then click Next: Tags

You can leave it blank and click Next: Review and Create user

Save your credential in safe place this is important. we’ll use it later.

Now we done setup our CodeDeploy let’s push our project to Github.

7. Push code to Github, setup secrets key and test

Create repository.

Commit and push our code up to master.

In our repository click Settings add our IAM key that we create above.

checkout new branch name it staging and push it to Github.

and push it to Github. get some coffee and watch actions running. if you seeing this result below, you are going in the right way.

From our CodeDeploy in AWS Console. you should see deployments just like below

Congratulations ! our CI/CD is now working.

You now can access your web app via IPv4 Public IP (you can find it from your EC2 Instance page in the description)

Next time you push or make pull request to staging branch, it will automatically run CI Pipeline & CD Pipeline for you.

You can create multiple development stage or have multiple pipeline that suit your work or even multiple instance for different stage.

Web Application | Software | IoT

www.codemonday.com