Wednesday, August 16, 2017

How to Dockerize a Node.js app?

The goal of this example is to show you how to get a Node.js application into a Docker container. In this article we'll show you how to create a Docker image for an application written in Node.js.

Why should I dockerize my application
You might've heard about the whole Docker thing, but that still doesn't answer the question: "why bother?" Well, that's why:

1. You can launch a fully capable development environment on any computer supporting Docker; you don't have to install libraries, dependencies, download packages, mess with config files etc.
2. The working environment of the application remains consistent across the whole workflow. 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 counter-measure for the age-old response in the software development: "Strange, it works for me!"

Part 1: Create the Node.js app
In the first part of this guide we will create a simple web application in Node.js, then we will build a Docker image for that application, and lastly we will run the image as a container.

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
First, create a new directory 'helloworld' where all the files would live and initialize npm.
 $ mkdir helloworld 
 $ cd helloworld
 $ npm init
When asked for the details of the application (name, version, etc.), just confirm the default values with enter.

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": "helloworld",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.15.2"
  }
}
With everything installed, we can create a server.js file that defines a web app using the Express.js framework with a simple HTTP server that will serve our Hello World website:
//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 server.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: pre-installed applications, dependencies, data bases, everything in 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 article, we'll look at how you can run this app inside a Docker container using the official Docker image.

Install Docker
Docker allows you to package an application with all of its dependencies into a standardized unit, called a container, for software development. A container is a stripped-to-basics version of a Linux operating system. An image is software you load into a container.

Begin with installing Docker for your type of OS: Docker installation

Write Dockerfile
The Docker image is created with instructions written in the Dockerfile. Let's add Dockerfile to the directory with our application. Create an empty file called Dockerfile:
 touch Dockerfile
Open the Dockerfile in your favorite text editor. The first thing we need to do is define from what image we want to build from.
Line 1: Use another Docker image for the template of my image. We shall use the official Node.js image with Node v8.
 FROM node:8.3.0
Line 2: Set working dir in the container to /app. We shall use this directory to store files, run npm, and launch our application:
 # Create app directory
 WORKDIR /app
Line 3-5: Copy application to /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. Please note that if you are using npm version 5 or later you will also want to copy package-lock.json, which is generated once you run npm install. This results from the way the Docker image is being built (layers and cache), and this is what we should do:
 # Install app dependencies
 COPY package.json /app

 # For npm@5 or later, copy package-lock.json as well
 # COPY package.json package-lock.json /app

 RUN npm install
Note that, rather than copying the entire working directory, we are only copying the package.json file. This allows us to take advantage of cached Docker layers.
To bundle your app's source code inside the Docker image, use the COPY instruction:
 # Bundle app source
 COPY . /app
Your app binds to port 8081 so you'll use the EXPOSE instruction to have it mapped by the docker daemon:
 EXPOSE 8081
Last but not least, define the command to run your app using CMD which defines your runtime. 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 server.js
Summing up, the whole Dockerfile should look like this:
 FROM node:8.3.0

 # Create app directory
 WORKDIR /app

 # Install app dependencies
 COPY package.json /app

 # For npm@5 or later, copy package-lock.json as well
 # COPY package.json package-lock.json /app

 RUN npm install

 # Bundle app source
 COPY . /app

 EXPOSE 8081
 CMD node server.js

.dockerignore file
Create a .dockerignore file in the same directory as your Dockerfile with following content:
 node_modules
 npm-debug.log
This will prevent your local modules and debug logs from being copied onto your Docker image and possibly overwriting modules installed within your image.

Build Docker image
Go to the directory that has your Dockerfile and run the following command to build the Docker image. The -t flag lets you tag your image so it's easier to find later using the docker images command:
 $ docker build -t hello-world .
Run the image
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 same port 8081:
 $ docker run -p 8081:8081 hello-world
Running your image with -p flag redirects a public port to a private port inside the container.

Print the output of your app
# Get container ID
$ docker ps

# Print app output
$ docker logs 

# Example
  app listening on port 8081!

We hope this tutorial helped you get up and running a simple Node.js application on Docker.

Sources:
Dockerizing a Node.js web app
How to Dockerize a Node.js application

No comments:

Post a Comment