DEV Community

Integration Ninjas
Integration Ninjas

Posted on

Deploy Node.js Application to AWS EC2 using GitLab CI

Introduction

Automating deployments with GitLab CI/CD is a powerful way to streamline your development workflow. In this guide, we'll walk through the process of deploying a Node.js application to an AWS EC2 instance using GitLab CI/CD and Docker. This setup ensures that every new commit is automatically built, pushed to a container registry, and deployed to your server.

Prerequisites

  • Node.js application: Ensure you have a Node.js application ready for deployment.
  • GitLab repository: Create or use an existing repository to host your application code.(Example Repo)
  • Docker installed: Install Docker locally(if running self-hosted runner) to build and manage container images. If you're running workflow with GitHub hosted runners then Docker is already installed there.
  • AWS account: Sign up for a free AWS account if you haven't already.
  • EC2 instance: Create an EC2 instance in AWS with appropriate specifications for your application. Configure security groups to allow inbound traffic on the port your application uses (e.g., port 3000).
  • SSH Client: Install an SSH client like PuTTY or Terminal (on macOS/Linux) to connect to your EC2 instance.

AWS EC2 Setup

  1. Use below commands to setup Docker:

    sudo apt-get update
    sudo apt-get install docker.io -y
    sudo systemctl start docker
    sudo docker run hello-world
    docker ps
    sudo chmod 666 /var/run/docker.sock
    sudo systemctl enable docker
    docker --version
    
  2. Use below reference to setup self-hosted runner on EC2:

Install GitLab Runner manually on GNU/Linux | GitLab

GitLab product documentation.

favicon docs.gitlab.com
  1. Once you create runner, use this reference to register the GitLab runner on that EC2 machine.

Flow Chart

CI/CD Workflow

Now, follow below steps to create required Docker file and .gitlab-ci.yml file to deploy you Node.js code on AWS EC2:

Step 1: Dockerizing the Node.js Application

First, let's create a Dockerfile to containerize our application:
Within your application directory, create a file named Dockerfile with the following content, replacing <IMAGE_NAME> with your desired image name and <PORT> with your application's port:

FROM node:20-alpine3.18
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 5000
CMD ["npm","run","start"]
Enter fullscreen mode Exit fullscreen mode

This Dockerfile:

  • Uses Node.js 20 on Alpine Linux for a lightweight image
  • Sets the working directory to /app
  • Installs dependencies
  • Copies the application files
  • Exposes port 5000 (adjust if needed)
  • Runs the application using npm run start

Build and test your Docker image locally:

docker build -t nodejs-app .
docker run -p 5000:5000 nodejs-app
Enter fullscreen mode Exit fullscreen mode

If everything works, move to the next step!

Step 2: Setting Up GitLab CI/CD Pipeline

To automate deployment, create a .gitlab-ci.yml file in your project root:

default:
  image: docker:24.0.5
  services:
    - docker:24.0.5-dind
  before_script:
    - docker info

stages:
  - build
  - deploy

build_job:
  stage: build
  script: |
    echo "Building the application.."
    docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
    docker build -t integrationninjas/nodejs-app:$CI_COMMIT_SHA .
    docker push integrationninjas/nodejs-app:$CI_COMMIT_SHA

deploy_job:
  stage: deploy
  script: |
    docker pull integrationninjas/nodejs-app:$CI_COMMIT_SHA
    docker rm -f nodejs-app-container
    docker run -d -p 5000:5000 --name nodejs-app-container integrationninjas/nodejs-app:$CI_COMMIT_SHA
  tags:
    - ec2-runner
  only:
    - deploy-to-ec2
Enter fullscreen mode Exit fullscreen mode

Understanding the Pipeline

  1. Default Section:

    • Uses Docker-in-Docker (dind) to enable Docker builds inside the GitLab Runner.
  2. Stages Section:

    • Defines two stages – build and deploy.
  3. build_job:

    • Logs into Docker Hub.
    • Builds the Docker image with the commit SHA as the tag.
    • Pushes the image to Docker Hub.
  4. deploy_job:

    • Pulls the latest image from Docker Hub.
    • Removes the old container (if running).
    • Runs the new container on port 5000.
    • Uses the GitLab Runner tag ec2-runner to execute on an AWS EC2 instance.
    • Triggers only when pushed to the deploy-to-ec2 branch.

Now, when you push changes to the deploy-to-ec2 branch, GitLab CI/CD will automatically build and deploy your app! 🚀

Step 4: Testing the Deployment

Once the pipeline completes, check if your app is running on EC2:

curl http://your-ec2-ip:5000
Enter fullscreen mode Exit fullscreen mode

You should see your application response! 🎉

Conclusion

With this setup, you've successfully automated the deployment of a Node.js application to AWS EC2 using GitLab CI/CD and Docker. Now, every commit to the deploy-to-ec2 branch will trigger an automatic build and deployment process. This approach ensures:

✅ Faster and reliable deployments
✅ Consistency across environments
✅ Less manual effort, thanks to automation.

💬 Questions? Drop them below! 🚀

Top comments (0)