Skip to content

Commit

Permalink
Sample NodeJS App for demo CI/CD using Jenkins to deploy on AWS ECS
Browse files Browse the repository at this point in the history
  • Loading branch information
shivalkarrahul committed Oct 9, 2021
0 parents commit f39fdbf
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 0 deletions.
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#Base Image node:12.18.4-alpine
FROM node:12.18.4-alpine


#Set working directory to /app
WORKDIR /app


#Set PATH /app/node_modules/.bin
ENV PATH /app/node_modules/.bin:$PATH


#Copy package.json in the image
COPY package.json ./


#Run npm install command
RUN npm install


#Copy the app
COPY . ./

EXPOSE 3000

#Start the app
CMD ["node", "./src/server.js"]
60 changes: 60 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
pipeline {
agent any
environment {
AWS_ACCOUNT_ID="CHANGE_ME"
AWS_DEFAULT_REGION="CHANGE_ME"
CLUSTER_NAME="CHANGE_ME"
SERVICE_NAME="CHANGE_ME"
TASK_DEFINITION_NAME="CHANGE_ME"
DESIRED_COUNT="CHANGE_ME"
IMAGE_REPO_NAME="CHANGE_ME"
IMAGE_TAG="${env.BUILD_ID}"
REPOSITORY_URI = "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_REPO_NAME}"
registryCredential = "CHANGE_ME"
}

stages {

// Tests
stage('Unit Tests') {
steps{
script {
sh 'npm install'
sh 'npm test -- --watchAll=false'
}
}
}

// Building Docker images
stage('Building image') {
steps{
script {
dockerImage = docker.build "${IMAGE_REPO_NAME}:${IMAGE_TAG}"
}
}
}

// Uploading Docker images into AWS ECR
stage('Pushing to ECR') {
steps{
script {
docker.withRegistry("https://" + REPOSITORY_URI, "ecr:${AWS_DEFAULT_REGION}:" + registryCredential) {
dockerImage.push()
}
}
}
}

stage('Deploy') {
steps{
withAWS(credentials: registryCredential, region: "${AWS_DEFAULT_REGION}") {
script {
sh './script.sh'
}
}
}
}

}
}

30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Sample NOdeJS Appl
------------------------

## Overview

CI/CD to test, build, push and deploy the NodeJS Dokerized app to AWS ECS using Jenkins Declarative Pipeline.

## Tech Stack

1. Github

2. Jenkins

3. ECR

4. ECS


## Pipeline Stages

1. Tests

2. Build an image

3. Push the image to ECR

4. Deploy the image


## Notes
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "nodejs-template-1.0",
"version": "1.0.0",
"description": "nodejs-template-1.0",
"main": "server.js",
"scripts": {
"test": "jest ./src/test",
"start": "PORT=3000 node src/server.js",
"build": "npm run-script build"
},
"dependencies": {
"jest": "^26.6.3",
"supertest": "^6.0.1"
}
}
21 changes: 21 additions & 0 deletions script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
ROLE_ARN=`aws ecs describe-task-definition --task-definition "${TASK_DEFINITION_NAME}" --region "${AWS_DEFAULT_REGION}" | jq .taskDefinition.executionRoleArn`
echo "ROLE_ARN= " $ROLE_ARN

FAMILY=`aws ecs describe-task-definition --task-definition "${TASK_DEFINITION_NAME}" --region "${AWS_DEFAULT_REGION}" | jq .taskDefinition.family`
echo "FAMILY= " $FAMILY

NAME=`aws ecs describe-task-definition --task-definition "${TASK_DEFINITION_NAME}" --region "${AWS_DEFAULT_REGION}" | jq .taskDefinition.containerDefinitions[].name`
echo "NAME= " $NAME

sed -i "s#BUILD_NUMBER#$IMAGE_TAG#g" task-definition.json
sed -i "s#REPOSITORY_URI#$REPOSITORY_URI#g" task-definition.json
sed -i "s#ROLE_ARN#$ROLE_ARN#g" task-definition.json
sed -i "s#FAMILY#$FAMILY#g" task-definition.json
sed -i "s#NAME#$NAME#g" task-definition.json


aws ecs register-task-definition --cli-input-json file://task-definition.json --region="${AWS_DEFAULT_REGION}"

REVISION=`aws ecs describe-task-definition --task-definition "${TASK_DEFINITION_NAME}" --region "${AWS_DEFAULT_REGION}" | jq .taskDefinition.revision`
echo "REVISION= " "${REVISION}"
aws ecs update-service --cluster "${CLUSTER_NAME}" --service "${SERVICE_NAME}" --task-definition "${TASK_DEFINITION_NAME}":"${REVISION}" --desired-count "${DESIRED_COUNT}"
13 changes: 13 additions & 0 deletions src/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var http = require('http');

var server = http.createServer(function(request, response) {

response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello, Welcome to DevOps CI CD");

});

var port = 3000;
server.listen(port);
module.exports = server
console.log("Server is available on Port:", port);
17 changes: 17 additions & 0 deletions src/test/server.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const app = require('../server'),
request = require('supertest');



describe('API Test',()=>{
afterEach(function (done) {
app.close(done)
});

it('Should return string in the GET Call',(done)=>{
request(app).get('/').expect('Content-Type',/text/).expect(200).end((error)=>{
if(error) throw done(error);
done();
});
});
});
23 changes: 23 additions & 0 deletions task-definition.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"family": FAMILY,
"containerDefinitions": [
{
"image": "REPOSITORY_URI:BUILD_NUMBER",
"name": NAME,
"essential": true,
"portMappings": [
{
"containerPort": 3000,
"hostPort": 3000
}
]
}
],
"cpu": "256",
"memory": "512",
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"executionRoleArn": ROLE_ARN
}

0 comments on commit f39fdbf

Please sign in to comment.