Best practices to containerize Node.js applications with Docker

Vipul Vyas
2 min readFeb 15, 2022

Till now we looked at how to create containerized node .js applications with docker. let’s see what is the point we need to consider while containerizing the node.js app.

some of the cases like.

  • your aim is to build a frontend application using server-side rendering (SSR) Node.js capabilities for React.

server-side rendering (SSR) : Server-side rendering (SSR) is an application’s ability to convert HTML files on the server into a fully rendered HTML page for the client. The web browser submits a request for information from the server, which instantly responds by sending a fully rendered page to the client.

  • you’re looking for advice on how to properly build a Node.js Docker image for your microservices, running Fastify, NestJS, or other application frameworks.

Let’s take the example of a simple node.js application.

Dockerfile

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

Run command to build and start the application.

$ docker build . -t simple-nodejs
$ docker run -p 3000:3000 simple-nodejs

all done. this simple node js application works fine with this. The only problem is It is full of mistakes and bad practices for building Node.js Docker images. Avoid the above by all means.

let’s see what is the problem and how to create a secure and optimized containerized node.js application.

Use explicit and deterministic Docker base image tags

It may seem to be an obvious choice to build your image based on the node Docker image, but what are you actually pulling in when you build the image? Docker images are always referenced by tags, and when you don’t specify a tag the default, :latest the tag is used.

FROM node

The shortcomings of the building based on the default node image are as follows:

  1. Docker image builds are inconsistent. Just like we’re using lockfiles to get a deterministic npm install behavior every time we install npm packages, we’d also like to get deterministic docker image builds. If we build the image from node—which effectively means the node:latest tag—then every build will pull a newly built Docker image of node. We don’t want to introduce this sort of non-deterministic behavior.
  2. The node Docker image is based on a full-fledged operating system, full of libraries and tools that you may or may not need to run your Node.js web application. This has two downsides. Firstly a bigger image means a bigger download size which, besides increasing the storage requirement, means more time to download and re-build the image. Secondly, it means you’re potentially introducing security vulnerabilities, that may exist in all of these libraries and tools, into the image.

In fact, the node Docker image is quite big and includes hundreds of security vulnerabilities of different types and severities. If you’re using it, then by default your starting point is going to be a baseline of 642 security vulnerabilities, and hundreds of megabytes of image data that is downloaded on every pull and build.

Part 5

--

--