Building A Node.js Application Using Docker

September 7, 2020

Docker allows us to run our applications as containers. A container is a standalone executable package that is lightweight and has everything needed to run an application be it libraries, tools, runtime, settings, or code.

In this tutorial, we will build a Node.js application, create an image, and also build a container using the image. Enjoy!

Dockerize the Node.js Application

To start this tutorial, we need to make sure Docker and Node.js are installed on our system. If Docker is not, you can refer to the links below to download:

To dockerize a Node.js application, we need to follow these steps:

  • Create a Node.js application
  • Create a Dockerfile
  • Building your Docker Image
  • Expose

Step 1 - Creating a Node.js Application

First, we will start by creating a directory for our project and then install some dependencies for our simple Hello World website.

 mkdir node-web-app
 cd node-web-app

Install npm And Express Framework

Install npm and Express, which is a Node.js framework. Then, initialize npm in our directory.

 npm init

npm creates a package.json that holds the dependencies of the app. Next, install the Express framework dependency.

 npm install express --save

Result:

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

Create an app.js file with an HTTP server that will set up the Hello World site:

//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 8080
app.listen(8080, function () {
  console.log('app listening on port 8080!')
})

Run The Application

The app is ready to launch:

$ node app.js

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

Step 2 - Create A DockerFile

Create a file in the root directory called Dockerfile.

The first thing is we need to define which image we want to build from. Here we will use version 9 of node available from Docker Hub:

FROM node:9

Next, create the working directory for your application.

# Create app directory
WORKDIR /app

Install the app dependencies using the npm binary.

# Install app dependencies
COPY package*.json ./

RUN npm install

Copy the rest of the application to the app directory.

COPY /app

Expose the port and start the application.

Expose 8080

CMD ["npm", "start"]

Your Dockerfile should look like this:

FROM node:9

# Create app directory
WORKDIR /app

# Install app dependencies
COPY package*.json ./

RUN npm install

# Copying rest of the application to app directory
COPY . /app

# Expose the port and start the application
Expose 8080

CMD ["npm","start"]

NOTE: Above you will notice we used two distinct COPY commands to reduce the application rebuild time

.dockerignore file

Create a .dockerignore file so as not to copy unnecessary files to the container:

node_modules
npm-debug.log

This prevents the local module and debug logs from being copied onto your Docker image.

Step 3 - Building your Docker Image

Building your Docker image is quite easy and can be done using a single command.

docker build -t <docker-image-name> <filepath>

The -t flag lets you tag your image so it’s easier to find later

For example:

docker build -t cisca .

Result:

Sending build context to Docker daemon  19.97kB
Step 1/7 : FROM node:9
9: Pulling from library/node
d660b1f15b9b: Pull complete
46dde23c37b3: Pull complete
6ebaeb074589: Pull complete
e7428f935583: Pull complete
eda527043444: Pull complete
f3088daa8887: Pull complete
1ded38ff7fdc: Pull complete
da44c9274f48: Pull complete
Digest: sha256:cddc729ef8326f7e8966c246ba2e87bad4c15365494ff3d681fa6f022cdab041
Status: Downloaded newer image for node:9
 ---> 08a8c8089ab1
Step 2/7 : WORKDIR /app
 ---> Running in cad30dfd3fdb
Removing intermediate container cad30dfd3fdb
 ---> 97cdf5dffbfd
Step 3/7 : COPY package*.json ./
 ---> fc4fa5670f19
Step 4/7 : RUN npm install
 ---> Running in 2e3c38322fd4
Removing intermediate container 2e3c38322fd4
 ---> 6b9912b8f798
Step 5/7 : COPY . /app
 ---> 33d29aad9ebe
Step 6/7 : EXPOSE 8080
 ---> Running in 8b2a54h557cc
Removing intermediate container 8b2a5ah557cc
 ---> 13b95635c201
Step 7/7 : CMD ["npm","start"]
 ---> Running in 50a5824edf5e
Removing intermediate container 50a5824edf5e
 ---> faa3092e5595
Successfully built faa3092e5595
Successfully tagged cisca:latest

You should get something similar to the output above after executing the command. This means that the docker image was created successfully and the app is working fine.

Now that the build is complete, you can check your image:

docker image ls

Result:

REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
cisca                         latest              faa3092e5595        4 minutes ago       675MB
node                          12-alpine           08a8c8089ab1        2 weeks ago         673MB

Step 4 - Run a Container

Now we can run the docker image using the command:

docker run -d -p <Host port>:<Docker port> <docker-image-name>

-d flag indicates the docker container is running in the background. The -p flag specifies which host port will be connected to the docker port.

Example:

docker run -d -p 8080:8080 cisca

Result:

34fe3040ff6b9d1b593a3c5d650ef0f16d53a989fe41816634456dd7f1341183

Conclusion

Use the docker ps command to check the running container.

docker ps -a

Result:

CONTAINER ID        IMAGE         COMMAND           CREATED              STATUS                          PORTS                    NAMES
34fe3040ff6b        cisca        "npm start"       About a minute ago   Exited (1) About a minute ago    0.0.0.0:8080->8080/tcp      intelligent_hofstadter

This tutorial has helped you with the basics of running a simple Node.js application using Docker and using a Dockerfile to build a Docker image. Here are a couple of other articles if you’d like more useful information on how to get started with Docker or more basics on understanding docker concepts for you to enjoy.

Resources

Dockerizing a Node.js web app

Dockerize

Understanding Docker Concepts

Getting Started with Docker


Peer Review Contributions by: Louise Findlay


About the author

Francisca Adekanye

Francisca is an undergraduate student pursuing a degree in Computer Engineering. Cisca loves technical writing, contributing to open source projects, and also involving herself in tech communities.

This article was contributed by a student member of Section's Engineering Education Program. Please report any errors or innaccuracies to enged@section.io.