cft

Step by Step Guide to Dockerize a Node.js Express Application

We will build an app and Dockerize it, so we will have our app running inside of a container, isolated from the outside world but reachable on ports that we explicitly open up.


user

Roland Hewage

a year ago | 5 min read

I covered what Docker is in my “What is Docker?” blog. We also understood that the thing that eventually runs an application is called a container. But how do we get there? Well, we start out with a description file, called a Dockerfile. In this Dockerfile, we specify everything we need in terms of OS, environment variables and how to get our application in there.

Now we will jump in at the deep end. We will build an app and Dockerize it, so we will have our app running inside of a container, isolated from the outside world but reachable on ports that we explicitly open up.

Part 1: Creating Node.js application

If you know the basics of Node.js, you can skip this part and proceed directly to the Docker part.

Here we will create a Node.js Express application, which will act as a REST API.

Install Node.js

If you’ve never worked with Node.js before, kick off with installing the npm manager: nodejs.org/en/download/package-manager

Install NPM and Express Framework

In addition to npm, our application will use the Express Framework, one of the most popular Node.js frameworks. Create a new directory and initialize npm:

npm init

When asked for the details of the application (name, version, etc.), just confirm the default values with enter or specify with your own details.

Npm will create a package.json 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": "dockerizeapp",
"version": "1.0.0",
"description": "My first docker app",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Roland Hewage",
"license": "ISC",
"dependencies": {
"express": "^4.15.2"
}
}

Details of dockerizeapp

With everything installed, we can create an index.js file with a simple HTTP server that will act as a REST API.

//Load express module with `require` directive
var express = require('express')
var app = express()//Define port
var port = 3000//Define request response in root URL (/)
app.get('/', function (req, res) {
res.send('Hello World!')
})//Launch listening server on port 3000
app.listen(port, function () {
console.log('app listening on port ${port}!')
})

Run the app

The application is ready to launch:

node index.js

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

Browser View

Part 2: Dockerizing Node.js application

Every application requires a specific working environment: pre-installed applications, dependencies, databases, everything in a specific version. Docker containers allow you to create such environments. Contrary to VM, however, the container doesn’t hold the whole operating system — just applications, dependencies, and configuration. This makes Docker containers much lighter and faster than regular VM’s.

In this part of the guide, we shall launch the previously created app in a Docker container.

Install Docker

Begin with installing Docker for your type of OS:

Write Dockerfile

The Docker container is launched on the basis of a Docker image, a template with the application details. The Docker image is created with instructions written in the Dockerfile. This file acts as a manifest but also as a build instruction file, how to get our app up and running. Let’s add Dockerfile to the directory with our application:

Line 1: Use another Docker image for the template of my image. We shall use the official Node.js image with Node latest version.

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

FROM node:latest
  • FROM, this is us selecting an OS image from Docker Hub. Docker Hub is a global repository that contains images that we can pull down locally. In our case we are choosing an image based on Ubuntu that has Node.js installed, it’s called node. We also specify that we want the latest version of it, by using the following tag :latest

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

WORKDIR /app
  • WORKDIR, this simply means we set a working directory. This is a way to set up for what is to happen later, in the next command below

Line 3–4: Here we copy the files from the directory we are standing into the directory specified by our WORKDIR command

COPY ..
RUN npm install

Line 5: Expose port 3000 to the outside once the container has launched:

EXPOSE 3000
  • EXPOSE, this means we are opening up a port, it is through this port that we communicate with our container

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"]orENTRYPOINT ["node", "index.js"]
  • ENTRYPOINT, this is where we should state how we start up our application, the commands need to be specified as an array so the array ["node", "index.js"] will be translated to the node index.js in the terminal

Summing up, the whole Dockerfile should look like this:

FROM node:latest
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
ENTRYPOINT ["node", "index.js"]

Ok, so now we have created all the files we need for our project and it should look like this:

index.js // our express app
Dockerfile // our instruction file that Docker will read from
/node_modules // directory created when we run npm install
package.json // npm init created this
package-lock.json // created when we installed libraries from NPM

Build Docker image

With the instructions ready all that remains is to run the docker buildcommand, set the name of our image with -t parameter, and choose the directory with the Dockerfile:

docker build [username]/[tag] [dockerfile location]//Example
docker build -t roland/node:latest .

The above instruction creates an image. The . at the end is important as this instructs Docker and tells it where your Dockerfile is located, in this case, it is the directory you are standing in.

If you don’t have the OS image, that we ask for in the FROM command, it will lead to it being pulled down from Docker Hub and then your specific image is being built.

Run Docker container

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

docker run -p 3000:3000 roland/node

We need to map the internal port of the app to an external one, on the host machine. Remember this is an app that we want to reach through our browser. We do the mapping by using the flag -p like so:

-p [external port]:[internal port]

Ok, running this command means we should be able to visit our container by going to http://192.168.99.100:3000, 3000 is our external port remember that maps to the internal port 3000. 192.168.99.100 is the machine IP docker is configured to use. This IP can vary based on your configuration. Let’s see, let’s open up a browser:

Browser View

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 hub.docker.com
  2. Build the image again using your Docker Hub credentials:
docker build -t [USERNAME]/hello-world .

3. Log in to Docker Hub with your credentials:

docker login

4. Push the image to Docker Hub:

docker push [USERNAME]/hello-world

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.

Upvote


user
Created by

Roland Hewage

I'm a Data Science, Machine Learning, Deep Learning, Quantum Computing Enthusiastic.


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles