How to Set Up a CI/CD Pipeline with Docker and GitHub Actions for Node.js Applications
In today's fast-paced software development environment, Continuous Integration (CI) and Continuous Deployment (CD) processes are vital for maintaining high-quality applications. For Node.js developers, integrating Docker and GitHub Actions into your CI/CD pipeline can streamline your development workflow, ensuring that your applications are tested and deployed with minimal manual intervention. In this article, we will explore how to set up a robust CI/CD pipeline using Docker and GitHub Actions for your Node.js applications.
What is CI/CD?
Continuous Integration (CI) is a development practice where code changes are automatically tested and merged into a shared repository multiple times a day. Continuous Deployment (CD) goes a step further by deploying these changes to production automatically after a successful CI build. Together, CI/CD helps teams deliver software faster, reduce integration issues, and maintain high code quality.
Why Use Docker?
Docker is a powerful tool that allows developers to package applications and their dependencies into containers, ensuring consistency across different environments. This means your application will run the same way on your local machine, in staging, and in production. Benefits of using Docker include:
- Isolation: Each application runs in its own container, preventing conflicts.
- Scalability: Easily scale applications by adding or removing containers.
- Portability: Docker containers can run on any platform that supports Docker.
Setting Up Your Node.js Application
Before we dive into the CI/CD setup, let’s ensure you have a basic Node.js application ready. If you don’t have one, create a simple server application.
Step 1: Create a Simple Node.js Application
mkdir my-node-app
cd my-node-app
npm init -y
npm install express
Create an index.js
file:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Step 2: Create a Dockerfile
Next, create a Dockerfile
in the root of your project directory:
# Use the official Node.js image.
FROM node:14
# Set the working directory.
WORKDIR /usr/src/app
# Copy package.json and package-lock.json.
COPY package*.json ./
# Install dependencies.
RUN npm install
# Copy the rest of the application code.
COPY . .
# Expose the application port.
EXPOSE 3000
# Define the command to run the application.
CMD ["node", "index.js"]
Step 3: Create a .dockerignore File
Create a .dockerignore
file to prevent unnecessary files from being copied into the Docker image:
node_modules
npm-debug.log
Setting Up GitHub Actions
GitHub Actions enables you to automate workflows directly from your GitHub repository. To create a CI/CD pipeline for your Node.js application using Docker, follow these steps.
Step 1: Create a GitHub Actions Workflow
In your project repository, create a directory called .github/workflows
and add a new file named ci-cd-pipeline.yml
.
Step 2: Configure the Workflow
Here’s a sample configuration for the CI/CD pipeline:
name: CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:latest
ports:
- 5432:5432
env:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: password
options: >-
--health-cmd "pg_isready -U user"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build Docker image
run: |
docker build -t my-node-app .
- name: Run tests
run: |
docker run my-node-app npm test
Step 3: Add Tests to Your Application
To ensure your application is functioning correctly, add tests. For example, you can use the jest
testing framework.
npm install --save-dev jest supertest
Create a test/app.test.js
file:
const request = require('supertest');
const app = require('../index'); // Adjust the path as necessary
describe('GET /', () => {
it('responds with Hello, World!', (done) => {
request(app)
.get('/')
.expect('Content-Type', /text/)
.expect(200, 'Hello, World!', done);
});
});
Step 4: Update the Workflow to Run Tests
Modify the workflow file to include the test step:
- name: Run tests
run: |
docker run my-node-app npm test
Troubleshooting Common Issues
- Docker Daemon Not Running: Make sure Docker is installed and running on your machine.
- Build Failures: Check the logs for errors during the Docker build process. Common issues include missing dependencies or incorrect paths.
- Test Failures: Ensure your tests are correctly written and your application is properly configured.
Conclusion
Setting up a CI/CD pipeline with Docker and GitHub Actions for your Node.js application not only automates your testing and deployment processes but also enhances code quality and team collaboration. By following this guide, you’ll be able to create a seamless workflow that accelerates your development cycle, allowing you to focus on building great applications.
Now that you have the foundational knowledge and tools at your disposal, you can further customize your CI/CD pipeline to fit your specific needs and scale your projects effectively. Happy coding!