This project demonstrates a complete CI/CD pipeline for a Node.js application, from code commit to deployment on an Amazon Elastic Kubernetes Service (EKS) cluster, leveraging GitLab CI/CD.
- Understanding Node.js
- Localhost Deployment and Testing
- Infrastructure Setup for Shared Runner
- Build and Test Stage
- SonarQube Stage
- Docker File Creation
- Docker Build and Push Stage
- Kubernetes Manifest File Creation
- Deployment Stage on EKS
- Project Summary
Node.js is an open-source, cross-platform JavaScript runtime environment that allows developers to execute JavaScript code on the server-side. It is built on Chrome's V8 JavaScript engine, enabling fast and efficient code execution.
- Web Servers: Building server-side applications and REST APIs.
- Real-time Applications: Developing interactive chat applications and other fast-processing systems.
- Microservices: Facilitating the creation of microservices architecture.
npm is the default package manager for Node.js, crucial for managing packages, dependencies, and scripts.
npm init: Initializes a project by creating apackage.jsonfile, which lists all project dependencies.npm install: Installs all dependencies listed inpackage.json.npm run: Helps in defining and running custom scripts (e.g., build, test).npm publish: Creates and publishes a package.
A typical Node.js project includes:
public/: Contains web page content (e.g., HTML, images).src/: Holds the application's source code.test/: Contains test cases.package.json: Lists all project dependencies.package-lock.json: Specifies the exact versions of dependencies used in the project.node_modules/: Directory where installed npm packages are stored.README.md: Project documentation.
Before deploying, it's essential to understand how the Node.js application behaves locally. Two scenarios are covered:
If the developer provides only the raw code, you need to build the project and install dependencies.
Steps:
- Install Node.js and npm: Follow the official Node.js installation steps for your operating system (e.g., Linux, Mac OS, Windows).
- Verify Installation: Check Node.js and npm versions using
node -vandnpm -v. - Install Dependencies:
- For
express(for viewing in browser):npm install express. - For
jest(for testing):npm install --save-dev jest.
- For
- Start the Server: Run
npm start. The application will typically run on port3000.
If node_modules and package-lock.json are already present, you can directly start the server.
Steps:
- Navigate to Project Directory.
- Start the Server: Run
npm start.
The project utilizes GitLab managed runners, eliminating the need for self-hosted runners or agents.
- GitLab Project: Create a new public project in GitLab (e.g., "project Node"). Enable testing for development purposes.
- SonarQube:
- Launch an EC2 instance (T3 medium or larger recommended due to SonarQube's resource requirements).
- Install JDK on the EC2 instance (SonarQube is Java-based).
- Create a dedicated
sonarqubeuser and set a password. - Add the
sonarqubeuser to thesudoerslist. - Download and unzip the SonarQube zip file into the
/optfolder. - Change the ownership of the SonarQube directory to the
sonarqubeuser. - Switch to the
sonarqubeuser. - Start SonarQube: Navigate to
sonarqube/bin/linuxand run the start script. - Access SonarQube on port
9000(e.g.,http://your-ec2-public-ip:9000). - Log in with default credentials (
admin/admin) and update the password.
- EKS Cluster:
- Create an EKS cluster (e.g., "Node.js cluster").
- Choose the standard version for cost efficiency.
- Utilize default VPC and security groups.
- Select the latest available add-on versions to avoid future upgrades.
- EKS cluster creation takes approximately 10-15 minutes.
This stage focuses on building and testing the Node.js application using GitLab CI/CD.
- Global Image: Specify a Node.js image (e.g.,
node:16). - Stages: Define
buildandteststages. - Build Job (
build_job):- Stage:
build. - Script:
npm install(to load dependencies).
- Stage:
- Test Job (
test_job):- Stage:
test. - Script:
npm test.
- Stage:
- SAST Job (Static Application Security Testing):
- Can be included to check for static vulnerabilities.
- Set
allow_failure: truefor SAST and SonarQube jobs to prevent pipeline failure if these checks fail.
- Initialize Git:
git init. - Add files:
git add .. - Commit changes:
git commit -m "Initial project files". - Add remote origin:
git remote add origin <your-gitlab-repo-url>. - Set upstream branch:
git branch -M main. - Push code:
git push -u origin main(orgit push -u origin --allif needed). - Ensure the branch is not protected in GitLab settings before pushing.
Once the .gitlab-ci.yml is committed, the pipeline will automatically trigger, running the build and test stages.
This stage integrates SonarQube for code analysis and quality checks.
- Configure GitLab Integration in SonarQube:
- Go to SonarQube settings and select "GitLab".
- Provide a name (e.g., "Node.js") and your GitLab URL.
- Generate a personal access token in GitLab with necessary permissions (e.g.,
api,read_repository,write_repository). - Paste the token into SonarQube and save the configuration.
- Create SonarQube Project: Select your GitLab project (e.g., "Project Node") and create a project in SonarQube using global settings.
Add the following variables in your GitLab project's CI/CD settings (Settings > CI/CD > Variables):
SONAR_TOKEN: Generate a new token in SonarQube for your project, copy its value, and set it as the variable value in GitLab. Uncheck "Protect variable" and check "Mask variable".SONAR_HOST_URL: Set the value to your SonarQube server URL (e.g.,http://your-ec2-public-ip:9000). Uncheck "Protect variable" and leave "Mask variable" unchecked.
Create a file named sonar-project.properties in your repository's root with the necessary SonarQube properties.
Add a sonarqube stage to your .gitlab-ci.yml file, including the SonarQube scanner commands.
After committing the changes, the pipeline will run, including the SonarQube analysis. The analysis results will be visible in the SonarQube dashboard.
A Dockerfile is essential for containerizing the Node.js application for deployment on Kubernetes.
Create a file named Dockerfile in your project's root:
# Base Image: Use Node.js 16 as the base image
FROM node:16
# Set Working Directory: Define the application's working directory inside the container
WORKDIR /usr/src/app
# Copy Package Files: Copy package.json and package-lock.json to install dependencies
COPY package*.json ./
# Install Dependencies: Run npm install to install project dependencies
RUN npm install
# Copy Application Code: Copy all application code to the working directory
COPY . .
# Expose Port: Expose port 3000, which Node.js typically uses
EXPOSE 3000
# Start Application: Define the command to start the Node.js server
CMD [ "npm", "start" ]