Node.js in a Docker Container

DevOps
Published May 7, 2022 ยท 3 min read
With the trend of containerizing software applications, we will go over how to run a node project in a Docker container.

Motivation

Eventhough running a Node.js project in a docker container might sound trivial, however, making it work out is so not. To start, we are assuming that you already have a Node.js project ready for this tutorial. 

Containerizing Node.js Project

The first step in containerizing any project is by adding a file to build its image. When using docker, this file is Dockerfile. So, add the following `Dockerfile` (without any extension) to your project.

FROM node:16.14.0-alpine AS build

RUN mkdir -p /app
WORKDIR /app

COPY package*.json /app/
RUN npm install

COPY . /app/
RUN npm run build

FROM nginx:alpine

COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist/{project_name}/usr/share/nginx/html

EXPOSE 80

As you may have noticed, this file follows the Docker Builder Pattern, which helps in reducing the size of the final image to limit its content to only contain the needed files.

In the first stage of the build (lines 1 to 10) where pulling node's base image and building our project. I chose the alpine version of node 16.14.0 which is a lighter edition of it. The output of this stage is a group of files that will constitute our final image's content, and it will be stored under the directory /app/dist/{project_name} of the file system of this stage (not visible in your local machine).

After we built our project, we need a webserver to run it in. For this tutorial I chose NGINX.

In the second stage (lines 12 to19), we are:

  1. pulling NGINX's alpine image
  2. copying NGINX's configuration file `default.conf` which we will talk about in a bit to it's required directory in our image
  3. copying the output of the build done in the build stage to NGINX's web root directory.
  4. exposing the port 80

Configuring NGINX

NGINX is more than just a web server, it can be used as a reverse proxy, load balancer, etc. Whichever you're using NGINX for, you will probably need to configure some of its behavior. 

In our example, we are using it as a web server. Without the line 14 of the Dockerfile, our web application will not have the best experience on refresh, as it will redirect us to 404 code error. To solve it, we need to create file named `default.conf` and copy it to the image as we are doing in line 14 of Dockerfile. The content of default.conf is below:

server {
  listen 80;
  root /usr/share/nginx/html;

  location / {
    try_files $uri $uri/ /index.html =404;
  }
}

In the above configuration, we are:

  1. listening on port 80
  2. specifying the webroot path, where our build content lives in
  3. adding a rule for all the paths in order to avoid immediately being redirected to the 404 error page.

Running the Container

To run the container, you can run the following commands:

docker build -i image_name .
docker run -dp 8080:80 image_name