How to Dockerize a Node.js application

Last updated May 11, 2021

How to Dockerize a Node.js application

Node.js and Docker. If you haven't spent the last decade in an underwater cave playing solitaire on a coral bed, you must have at least heard of these two ever-trending techs in the web development industry. In this article, we'll merge both and show you how to write a Dockerfile for a Node.js application, build a Docker image of it, and push the image to a Docker registry.

Why should I Dockerize my application

You might've heard about the whole Docker thing, but that still doesn't answer the question of why you should bother at all. Well, here's why:

  • A Docker image is a self-contained unit that bundles the app with the environment required to run it. No more installing libraries, dependencies, downloading packages, messing with config files, etc. If your machine supports Docker, you can run a Dockerized app, period.
  • The working environment of the application remains consistent across workflows and machines. This means the app runs exactly the same for developer, tester, and client, be it on development, staging, or production server.

In short, Docker is the modern-day counter-measure for the age-old "strange, it works for me!" response in software development.

If you're not sure that you fully understand the idea of Docker containers, watch this short video by TechSquidTV to get up to speed:

Part 1: Creating Node.js application

We'll start by creating a simple Hello World app, a staple of every web developer's portfolio. The app will use Express, one of the most popular Node.js frameworks.

If you're familiar with the basics of Node.js, you can jump ahead to the part on Docker and use the ready app from our repository as the base.

You can also sign up to Buddy with your Git provider and select repository with your Node app:

Install Node.js and npm

If you've never worked with Node.js before, start by installing npm – the Node.js package manager. Click here to choose the right version for your environment.

Node.js is bundled with npm, so one installation gets you both of them.

Initialize Project and Install Express.js

Create a new directory for the app and initialize a Node project:

mkdir helloworld
cd helloworld
npm init
$$$

When asked for the details of the application, set the name to helloworld. For other options, just confirm the default values with enter.

If you are lazy value your time, run npm init --yes to create a project instantly with default settings.

Npm will create a package.json file that will hold the dependencies of the app. Let's add the Express framework as the first dependency:

npm install express --save
$

The file should look like this now:

{
  "name": "helloworld",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  }
}

TableMain of Hello World

With everything installed, we can create an index.js file with a simple HTTP server that will serve the Hello World app:

//Load express module with `require` directive
var express = require('express')
var app = express()

//Define request response in root URL (/)
app.get('/', function (req, res) {
  res.send('Hello World!')
})

//Launch listening server on port 8081
app.listen(8081, function () {
  console.log('app listening on port 8081!')
})

Run the app

The application is ready to launch:

node index.js
$

Go to http://localhost:8081/ in your browser to view it.

Part 2: Dockerizing Node.js application

Every application requires a specific working environment: applications, dependencies, databases, libraries, everything in a specific version. Docker allows you to create such environments and pack them into a container.

Contrary to a VM, the container doesn't hold the whole operating system — just the applications, dependencies, and configuration. This makes Docker containers much lighter and faster than regular VMs.

In this part of the guide, we will build a Docker container with the Hello World app, and then launch the app in a Docker container.

If you didn't configure the app in the first part of the guide, you can fork a working Node project from our repository on GitHub.

Install Docker

Begin with installing Docker on your machine:

Write Dockerfile

The Docker container is launched from a Docker image, a template with the application details. The Docker image is created with instructions written in the Dockerfile. Each line in the Dockerfile is a separate instruction run from top to bottom (the order is important for proper optimization).

Add a Dockerfile to the directory with your application and configure the lines as described below.

Line 1: We shall use the official Node.js image with Node v12 as the template for our image

You can share images using image registries. In this example we'll use Docker Hub, the most popular one.

FROM node:12

Line 2: Set the working directory in the container to /app. We shall use this directory to store files, run npm, and launch our application:

WORKDIR /app

Lines 3-5: Copy the application to the /app directory and install dependencies. If you add the package.json first and run npm install later, Docker won't have to install the dependencies again if you change the package.json file. This results from the way the Docker image is being built (layers and cache), and this is what we should do:

COPY package.json /app
RUN npm install
COPY . /app

Line 6: This line describes what should be executed when the Docker image is launching. What we want to do is to run our application:

CMD node index.js

Line 7: Expose port 8081 to the outside once the container has launched:

EXPOSE 8081

Summing up, the whole Dockerfile should look like this:

FROM node:12
WORKDIR /app
COPY package.json /app
RUN npm install
COPY . /app
CMD node index.js
EXPOSE 8081

If you'd like to deepen your knowledge on writing Dockerfiles, check out this excellent guide on the Docker's website.

Build Docker image

With the instructions ready, all that remains is to run the docker build command, set the name of your image with -t parameter, and choose the directory where the Dockerfile is located:

docker build -t hello-world .
$

Run Docker container

The application has been baked into the image. Dinner time! Execute the following command to launch the container and publish it on the host with the same port 8081:

docker run -p 8081:8081 hello-world
$

Sharing Docker image

Docker images can be hosted and shared in special image registries. The most popular is Docker Hub, a GitHub among Docker registries, in which you can host private and public images. Let's push an image to Docker Hub now:

  1. Sign up at Docker Hub
  2. Build the image again using your Docker Hub credentials:
docker build -t [USERNAME]/hello-world .
$
  1. Log in to Docker Hub with your credentials:
docker login
$

Logging in to Docker HubLogging in to Docker Hub

  1. Push the image to Docker Hub:
docker push [USERNAME]/hello-world
$

Docker image on Docker HubDocker image on Docker Hub Congratulations! You can now use the image on any server or PC with Docker installed:

docker run [USERNAME]/hello-world
$

Please mind the image needs to be downloaded on the first run which may take some time depending on your connection.

Deploying Dockerized application to server

Launching a Docker image on the server is as simple as running docker pull and docker run in the desired location. However, whenever you update your application, it requires you to repeat the following steps:

  1. Test if the application is free of errors
  2. Build the Docker image
  3. Push the image to the registry
  4. Pulling and running the image on the server

These steps are simple, but can be time-consuming and prone to errors if done manually. The whole process, however, can be streamlined to a repository push with a properly configured pipeline. With Docker layer caching included in every plan, from free to premium, Buddy gets the job done in a blink of an eye, allowing you to track the progress of your project with full history of every pipeline execution.

Share

About the Author
Alexander Kus

Alexander Kus

Customer Success Manager

A story-teller and conversation-lover, Alexander decided to invest his skills to help his friends at Buddy transform the cold language of patch notes into exciting narratives. Also: an avid gamer, hip-hop DJ, Liverpool FC fan, absentminded husband, and the father of two.

Buddy Makes Developers Happier

You use lots of tools to get web & app development done. Buddy creates more time in your day by helping you automate those tools.

Sign up for free with