Trick: How to significantly reduce NPM download time for NodeJS Web application on Docker image

Kobkrit Viriyayudhakorn
Kobkrit
Published in
2 min readMay 1, 2018

--

Docker made my life much easier! I put every web application project to its own docker container. Docker allows me to deploy web application server on any cloud or any service providers. We can customize the dependencies to any versions of libraries that we want to use, and also integrated well with any continuous integration tools (like Jenkins).

Docker is excellent, but, the biggest drawback of Docker compared to the traditional FTP upload to server, it requires significant amount of time to complies a docker image. Generally for moderate size of web application project, it takes about 6–8 minutes to produce an image.

Turn out, I found the way to optimize the time to produce an image, especially for NodeJS Web application. Most of docker image compile time is wasted due to NPM install. It contributes 95% of the time. With simple Dockerfile modification, I can reduce from 6 minute to 10 seconds for building an image if the dependencies is not changed.

Instead of writing Dockerfile in the popular format like this.

FROM node:9
MAINTAINER Kobkrit Viriyayudhakorn (kobkrit@iapp.co.th)
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app/
RUN npm install
CMD [ "npm", "start" ]EXPOSE 4000

Change to this.

FROM node:9MAINTAINER Kobkrit Viriyayudhakorn (kobkrit@iapp.co.th)ADD package.json /tmp/package.json
RUN cd /tmp && npm install
RUN mkdir -p /usr/src/app && cp -a /tmp/node_modules /usr/src/app/
WORKDIR /usr/src/app
COPY . /usr/src/app/
CMD [ "npm", "start" ]EXPOSE 4000

The key ideas is to change from running ``npm install`` every time when your web changes to running only when its dependencies changed. We caches the whole node_modules folder, and save it to a docker commit. If your dependencies are not changed, docker can reuse the old commit for building the new one, significantly saving your docker image building time!

The following are improvement in a real work.

I change to the new Dockerfile on build #6. I changed dependencies on build #8, and #11.

In build #1-#5, I used the first Dockerfile. I changed to the latter on build #6. In build #7, it has no dependencies changed, but in build #8, it has some dependencies change which need to re-run npm install.

--

--