Node and Docker are a match made in heaven because the strengths of Node play to the strengths of Docker. Node microservices typically are built on top of the Express web server which can be configured with “just enough” server and run an application. Additionally, the Node package manager, NPM, makes installing and running Node apps a cinch and keeps Node’s footprint to a minimum. The combined effects of Node’s model make it an ideal candidate for Docker.

To make life easier with Node, use a package.json file. Having Using the package.json enables Docker to leverage NPM to install dependencies just like when running the app locally. Also setting the main property in the package.json enables Docker to easily start the application.

package.json

{
  "name": "node-docker",
  "version": "1.0.0",
  "description": "A simple node demo app",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "express": "^4.16.2"
  }
}

Most container images start with a base image. Because Node has an independent package management system apart from a given operating system’s package management. For this reason, it is best to choose a more minimalistic image such Node built on Alpine. Doing so makes the image more secure and smaller.

Dockerfile

FROM node:alpine
COPY . /app
WORKDIR ./app
RUN npm install
CMD npm start

This Dockerfile sample copies the application into a folder in the root of the container images file system called app, sets the working directory to that folder, then calls npm install. If the package.json is present, NPM will read it and install of the application dependencies for the specific platform. You may also want to include other things like environmental variables and exposed ports in your application. You can use ENV for variables and EXPOSE for ports respectively in your Dockerfile.

In addition to the Dockerfile, you’ll want to set up a .dockerignore file. This file is like a .gitignore file. It tells Docker build to ignore certain kinds of files or directories. In the case of node, you’ll want to ignore the node_modules folder. Simply create a text file called .dockerignore that has 1 line it it:

.dockerignore

node_modules

Once the Dockerfile and the .dockerignore files are in place, youre ready to build the image. With a shell (CMD, Powershell, Bash etc.) in the app directory, you can run the following command.

docker build --tag my-docker-image .

This tells docker build to look in the current directory for a Dockerfile, which should exist. It then uploads all the content in the folder (minus what is ignored) to the Docker engine and then builds the image. Given that this is mostly just text files, the upload is small. You can watch the build output and see where the build installs all of the node modules declared as dependencies in the package.json.

Once the container is built, you can run it or push it to a repository. All in all, working with Docker and Node is straight forward and requires very little effort to make it work.

Here’s a working example app that uses the above files verbatim. Happy Dockering!