How to deploy a Node.js API using docker and Nginx.

How to deploy a Node.js API using docker and Nginx.

Docker + Node.js + Nginx

I was working on my own backend API to handle my portfolio data, but later I thought of switching the API to be used primarily as an app to manage my Twitter account activity, and soon some more integrations like this hashnode blogs, and GitHub as well. But the question is how to put these applications into production, so here’s the solution.

We will be using the same API i.e, knowme.API (the name I give it) for instance to understand the concept. I assume that if you are reading this blog you already know some docker concepts like Dockerfile, docker-compose, etc.

Dockerizing a Node.js Application:

Here’s the sample dockerfile to dockerize a node.js REST API

FROM node:latest
WORKDIR /knowme-api
COPY package*.json /knowme-api/
RUN npm install 
COPY . .
RUN npx prisma generate
RUN npm run build
ENV PORT=$PORT
EXPOSE 3000
CMD ["npm", "start"]

Steps:-

  • Selecting which docker base image to start with, here I took node.js of the latest version.

  • Setting up the working dir of your application inside the container.

  • Copying the package.json and package.lock.json files into the working directory to install the modules to escape any kind of error.

  • Installing modules.

  • Copying the rest of the code from the root of the project ( the same dir in which Dockerfile is ) to the current dir in a working directory set up in step 1.

  • Building the project, here because I am working with typescript, if you are on JS, you can skip this step.

  • Then set up all the environment variables needed by the container or application to run smoothly.

  • Exposing the port.

  • Starting the application.

  • Build the docker image using :

docker build -t {tag here} {path-to-your-dockerfile}

Serving Node application using the running instance of Nginx:

Wanna know what Nginx is and why we are even using it here, you can refer to this Twitter thread here.

Let’s hop onto our main agenda which is setting up your node.js API to be served by Nginx using docker.

Creating the config file to set the reverse proxy:

  • Create a directory at the root of your project named Nginx.

  • Create an nginx.conf file in the same nginx dir and add the following code.

user root;
worker_processes auto;

pid /var/run/nginx.pid;

events {
  worker_connections 1024;
}

http {
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_x_forwarded_for" ';

  client_body_buffer_size     32k;
  client_header_buffer_size   8k;
  large_client_header_buffers 8 64k;
  sendfile on;
  # tcp_nopush     on;

  keepalive_timeout 65;

  #gzip  on;
  server {
    listen 80;

    server_name knowme_api;
    large_client_header_buffers 4 32k;

    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log debug;

    location / {

      proxy_http_version 1.1;
      proxy_cache_bypass $http_upgrade;

      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_pass http://knowme_api:3000;

  }

}
}

NOTE: Point to remember here is that proxy_pass is the destination URL to redirect requests received by port 80 at localhost in our case. We are using it as http://knowme_api:300, because our node application is running in a container named knowme_api, you need to substitute it with whatever your container name is as mentioned in the later docker-compose file.

Setting up Nginx using Docker:

Create a Dockerfile there in the dir, and put the following code:

FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf

RUN unlink /var/log/nginx/access.log
RUN unlink /var/log/nginx/error.log

EXPOSE 80

These are five simple steps we need to add to our Dockerfile.

  • Selecting docker image, so we do have an official nginx docker image which will provide us Linux environment with Nginx installed on that so let's use it only.

  • Then we are copying the Nginx main configuration file that we will be creating in the previous section.

  • Unlinking the soft link of access logs and error logs files, set up by default by the nginx docker distribution. Refer here

  • Exposing port 80 of the container, port 80 because it's the default port for HTTP traffic.

Setting up docker-compose:

Create a docker-compose file and populate it with two services, one is your app and the second one is the nginx server.

version: '3.9'

services:
  api:
    container_name: knowme_api
    build: './'
    ports: 
    - 3000:3000
    env_file: './.env'

  nginx: 
    container_name: nginx_service
    build: './nginx/'
    ports:
      - 80:80
    restart: always

Use docker-compose up --build to start the application and serve it through the Nginx. Visit localhost on your PC, your app must be visible there. If in any case you face any bug or issue you can reach out to me at the socials given below.

Do share the blog, if it helped you. ✨✨

Twitter Linkedin GitHub