Containerize Node.js web applications with Docker

Photo by Ian Taylor on Unsplash

Containerize Node.js web applications with Docker

Introduction to nodejs and docker

In this article, we are going to look at how to containerize our NodeJs application and we will look into what benefits of containerizing our application.

In the first part, we will initialize a NodeJS application first then go through all the processes of connecting with the database and all. After that, we will look into some useful docker commands we need to know.

So let's get started.

Create a NodeJS app

First of all, let's create a package.json file by running this command in your app directory. I am creating my project inside the app directory you are free to name whatever you want. Inside the app directory run the following command npm init -y this will automatically create package.json file with some text something similar to this.

{
  "name": "docker-nodejs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

After this, we will install a few packages such as express and nodemon. We will install nodemon as a dev dependency by running this command npm install -D nodemon and express as dependencies by this command npm install express. Now we are ready to write some code.

let's create index.js file and add the following code to it.

const express = require('express');

const app = express();

app.use(express.json());

app.get('/', (req,res,next) => {
       res.send(`<h1>Hello world </h1>`)
})


const PORT = process.env.PORT || 3000;
app.listen(PORT, ()=> console.log(`app is running at ${PORT}`));

Here we have created our first route which will display Hello world on the screen when we will navigate to localhost:3000/. Before that, we need to make some changes in our package.json file as well.

{
  "name": "docker-nodejs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev":"nodemon index.js",
    "start":"node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

So here we just added two scripts npm run dev when we run this command in our terminal and make changes to our code it will reflect immediately on the screen. And when we run npm start it will just display our current code and after every changes, we need to restart the server.

Now we have a basic setup ready. We are ready to introduce Docker now.

let create a docker file inside our app directory and add these codes to it.

FROM node:15
WORKDIR /app
COPY package.json .
RUN npm install

COPY  . ./
ENV PORT 8080
EXPOSE $PORT

CMD ["node", "index.js"]

Let me explain every line of code here.

In the first line, we have added FROM node:15 which means docker will pull the node from the docker hub with version 15. After that in the next line, we are defining our working directory this exact directory will be created inside our container. Later docker will run this command COPY package.json . this command is going to copy package.json file to our working directory inside the container. Then npm install will install all the dependencies inside our container and will also create node_modules directory inside our container. Now the COPY . ./ command will copy all the files from our current directory to the container's working directory.

The next line ENV PORT 8080 will set the environment variable inside our container which we can grab inside index.js by process.env.PORT.

EXPOSE $PORT this command is just giving us a port through which we can access our app in our local environment outside of the container. And then we have added a command CMD ["node", "index.js"] by default docker will run this command. Hope this all explanation makes sense to you.

Now for the performance optimization, we don't want to copy our host node_modules to our container. The container is going to have its own node_modules file remember we have added npm install inside our Dockerfile.

So to stop Docker to copy node_modules from the host to the container we will create a file called .dockerignore and add these lines.

node_modules
.env
Dockerfile
.dockerignore
.git
.gitignore
docker-compose*

I have added some additional lines which we are going to need later.

After all these setups is ready to run our docker command.

docker build  -t docker-nodejs .

Here I have added -t flag to add the name of our image.

After running the above command your terminal output will look something like this if you have done everything correctly.

Screenshot 2021-12-21 at 8.59.23 PM.png

To check if the image is built properly you can run this command.

docker image ls

It will give out something like this.

Screenshot 2021-12-21 at 9.06.41 PM.png

Now our image is ready. Let's run our image by using this command.

docker run -p 3000:8080 -d --name node-app docker-nodejs

Here before running the container we have added --name flag to give a name to our container in which our docker-nodejs image will run. And I have also added -d flag which means to run this container in detach mode. I have also added -p flag which basically maps port 8080 from the container to port 3000 in the host container. This means when we run the app in our browser we need to visit localhost:3000/.

Screenshot 2021-12-21 at 9.49.32 PM.png

The result will look something like the above image in your browser.

Hope this article helps you understand a little bit of how to build an image and run inside a container. In the next post, we will discuss the docker-compose and try to go into more detail.

To support.

Did you find this article valuable?

Support adityakmr by becoming a sponsor. Any amount is appreciated!