How to Containerize a Node.js Microservice with Docker

How to Containerize a Node.js Microservice with Docker

Introduction

In this tutorial, you will learn how to containerize a Node.js microservice using Docker. Containerization allows you to package your microservice and its dependencies into a single, portable unit that can run consistently across different environments. We'll walk through each step, provide the necessary commands, and explain key technical terms.

Prerequisites

Before you begin, make sure you have the following prerequisites:

  1. Node.js installed on your development machine.

  2. Docker installed on your development machine. You can follow the official Docker installation guide to install Docker for your platform.

Step 1: Develop a Node.js Microservice

First, let's create a simple Node.js microservice. You can use your own microservice code or create a simple example using Express.js.

  1. Create a new directory for your microservice:

     mkdir node-microservice
     cd node-microservice
    
  2. Initialize a Node.js project and install Express:

     npm init -y
     npm install express
    
  3. Create a basic Express.js microservice in an app.js file:

     const express = require('express');
     const app = express();
     const port = process.env.PORT || 3000;
    
     app.get('/', (req, res) => {
       res.send('Hello, Microservice!');
     });
    
     app.listen(port, () => {
       console.log(`Microservice is running on port ${port}`);
     });
    
  4. Save the changes and exit your code editor.

Step 2: Write a Dockerfile

A Dockerfile is used to define the environment and instructions for building a Docker image. In this step, we'll create a Dockerfile for your Node.js microservice.

  1. Create a file named Dockerfile in the root of your microservice directory:

     touch Dockerfile
    
  2. Open the Dockerfile in a text editor and add the following content:

     # Use an official Node.js runtime as the base image
     FROM node:14
    
     # Set the working directory within the container
     WORKDIR /app
    
     # Copy the package.json and package-lock.json files to the container
     COPY package*.json ./
    
     # Install project dependencies
     RUN npm install
    
     # Copy the rest of the application code to the container
     COPY . .
    
     # Expose a port for your microservice
     EXPOSE 3000
    
     # Define the command to start your microservice
     CMD ["node", "app.js"]
    

    This Dockerfile specifies a Node.js base image, sets up the working directory, copies the project files, installs dependencies, exposes a port, and defines the command to start the microservice.

Step 3: Install Docker

If you haven't already installed Docker, here are the steps to install it:

Linux Installation

  1. Update your package manager:

     sudo apt-get update
    
  2. Install necessary packages:

     sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
    
  3. Add Docker's official GPG key:

     curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    
  4. Add the Docker repository to your sources list:

     echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
  5. Update the package list to include Docker and install it:

     sudo apt-get update
     sudo apt-get install docker-ce -y
    
  6. Add your user to the docker group to run Docker commands without sudo:

     sudo usermod -aG docker ${USER}
    
  7. Activate the changes to groups:

     su - ${USER}
    
  8. Verify that Docker is installed and running:

     sudo systemctl status docker
    

Windows Installation

  1. Download the Docker Desktop for Windows installer and follow the installation instructions.

macOS Installation

  1. Download the Docker Desktop for Mac installer and follow the installation instructions.

Step 4: Build the Docker Image

Now that you have a Dockerfile, you can build a Docker image for your Node.js microservice.

  1. Open your terminal and navigate to the root of your microservice directory.

  2. Build the Docker image using the docker build command. Replace <image-name> with a name for your image, and optionally add a tag (e.g., v1.0) for versioning:

     docker build -t <image-name>:<tag> .
    

    For example:

     docker build -t my-node-microservice:v1.0 .
    

    Docker will execute the instructions in your Dockerfile, creating an image for your microservice.

Step 5: Run Multiple Instances with Docker Compose

Docker Compose is a tool for defining and running multi-container Docker applications. In this step, we'll use Docker Compose to run multiple instances of your microservice.

  1. Create a docker-compose.yml file in your microservice directory:

     touch docker-compose.yml
    
  2. Open the docker-compose.yml file in a text editor and add the following content:

     version: '3'
     services:
       microservice:
         image: my-node-microservice:v1.0
         ports:
           - 3000:3000
    

    This docker-compose.yml file defines a service named "microservice" based on the Docker image you built earlier. It maps port 3000 on your host to port 3000 in the container.

  3. Save the changes and exit your code editor.

  4. Run your microservice using Docker Compose:

     docker-compose up
    

    This command starts your microservice within a Docker container.

Step 6: Implement Service Discovery with Docker Networking

Docker provides built-in networking features that allow containers to communicate with each other. By default, containers launched by Docker Compose can resolve

each other's service names as hostnames.

In your Node.js microservice, you can connect to another microservice using its service name as the hostname.

For example, if you have another microservice running and named "other-service" in your docker-compose.yml, you can make an HTTP request to it like this:

const axios = require('axios');

axios.get('http://other-service:3000')
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.error(error);
  });

By using Docker Compose and Docker's built-in networking, you can easily implement service discovery between microservices.

Conclusion

You've successfully containerized a Node.js microservice using Docker. This allows you to package your microservice and its dependencies into a portable unit that can be deployed consistently across different environments. You've also learned how to run multiple instances of your microservice with Docker Compose and implement service discovery using Docker networking.

Key Terms & Meaning:

  • Dockerfile: A script used to create a Docker image, defining the environment and instructions for building a container.

  • Docker Image: A lightweight, stand-alone, executable package that includes everything needed to run a piece of software, including the code, runtime, system tools, and libraries.

  • Docker Compose: A tool for defining and running multi-container Docker applications.

  • Service Discovery: The process of automatically detecting and connecting to available services in a network, often used in microservices architectures.

  • Docker Networking: Docker's networking features that allow containers to communicate with each other using service names as hostnames.

Did you find this article valuable?

Support Gordian Etim by becoming a sponsor. Any amount is appreciated!