Create CI/CD with Github Actions + AWS EC2, CodeDeploy and S3
What’s gonna happen? (TLDR)
- When you push or merge into specific branch (staging, master etc.) Github Actions will trigger CI Pipeline (Build & Test). If passed it will trigger CD Pipeline (Deployment).
- All of this are automated by Github Actions and AWS CodeDeploy.
Prerequisite
You’ll need an AWS account that can do the following
- Launch EC2 Instance
- Create S3 Bucket
- Create IAM account
- Create IAM Role
Steps
- Create IAM Role for EC2 instance & CodeDeploy
- Launch EC2 Instance for our application
- Create S3 bucket for our application revision
- Setup our project for CodeDeploy, PM2 and Github Workflows
- Setup CodeDeploy
- Create IAM account
- Push code to Github, setup secrets key and test
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
thenRole
. - Select
Create role
.
Create Role for EC2 instance
This role will allow EC2 to communicates with CodeDeploy
- Select
EC2
as a use case, then clickNext: 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 clickNext: Review
- Give it a name
CodeDeployInstanceRole
or any name you want.
Create Role for CodeDeploy
This role will allow CodeDeploy to communicates with EC2,
- From create role screen, scroll down and select
CodeDeploy
as a use case, then clickNext: 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 clickLaunch Instance
In this article i’ll use Ubuntu Server 18.04 LTS as a machine image.
- Search for
Ubuntu
then clickSelect
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 selectCodeDeployInstanceRole
. 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
andregion-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 bewget https://aws-codedeploy-ap-southeast-1.s3.ap-southeast-1.amazonaws.com/latest/install
#!/bin/bash
sudo apt-get update
sudo apt-get install ruby
sudo apt-get install wget
cd /home/ubuntu
wget https://bucket-name.s3.region-identifier.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
sudo service codedeploy-agent startcurl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejssudo npm install pm2 -g
This script will install CodeDeploy Agent, NodeJS and PM2 on our instance in launch time.
- Click
Next: Add Storage
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.
You 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 clickCreate bucket
- Give it a name
aws-codedeploy-deployments
or any name you like and don’t for get to selectBlock all public access
this is important. clickCreate 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
thenApplications
- Click
Create application
, give it a name and chooseEC2/On-premises
and clickCreate application
- inside our application click
Create deployment group
give it a name (in this case we name it after our stage that isstaging
). Select roleCodeDeployServiceRole
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?). - 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
andclick 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
andUser
and clickAdd user
. selectProgrammatic access
then clickNext: Permission
- Add this two permission to this user then click
Next: Tags
- You can leave it blank and click
Next: Review
andCreate 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. - 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