DEV Community

Nova Script
Nova Script

Posted on

[DOCKER] [NODE]: How to rebuild node_modules only when it's necessary!

Introduction:

Not everytime we change our code it means that we have implemented new dependencies: if we have not inserted a new package into our project, there's no reason at all to rebuild node_modules folder.

So let's understand how we can upgrade our efficiency, as your development and debugging time for Node applications running Docker will be significantly reduced.

How Node Dockerfiles are usually implemented:

Let's take a fast look at this usually seen Dockerfile, which is bad implemented.

FROM node:16

# Create app directory
WORKDIR /usr/src/app

# Copy source
COPY . .

# Install dependencies
RUN npm install

# Run server
EXPOSE 8080
CMD [ "node", "server.js" ]
Enter fullscreen mode Exit fullscreen mode

The whole efficiency problem here is located at COPY . .

This is bad. Doing so will result in: everytime we make a change to a file in ., our modules folder will have to be built again and again and again...

Fixing it:

Instead, we should firstly only copy our package.json and package-lock.json files (which controls our dependencies) to our working directory and then install them.

So, let's update our Dockerfile to:

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install
Enter fullscreen mode Exit fullscreen mode

And only then, we can copy the rest of our files:

COPY . .
Enter fullscreen mode Exit fullscreen mode

So, our fixed Dockerfile version will be:

FROM node:16

# Create app directory
WORKDIR /usr/src/app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy source
COPY . .

# Run server
EXPOSE 8080
CMD [ "node", "server.js" ]
Enter fullscreen mode Exit fullscreen mode

Explanation:

It's all about Docker cached layers.

Each Docker image consists of a series of layers.

Commands in your Dockerfile will always generate new layers.

Instead of keeping everything within only one layer, we should break it on different parts.

Because Docker will try to use an existent cached layer on rebuild.

That's the simple explanation.
You can read the details on official documentation.

Conclusion:

Now, everytime package.json file changes, npm install will be runned again. Otherwise, it will be simply skipped.

You can check this behavior on your log: just look for ---> Using cache, which indicates node_modules is not being rebuilded.

Liked this post? ;D

If you do, please consider following me or favoriting this post!

Top comments (0)