Docker Image Optimization for Node.js
Last Updated :
12 Jul, 2024
Docker is the most widely containerization tool that developers to deploy applications to production with little to no downtime. In this article, we are going to learn how Docker images can be optimized for Node.js applications for better performance, stability, and security.
Prerequisites
- Docker installed
- Basic knowledge of Node.js
What is Docker Image
We know a container is an isolated environment, but from where container get files and configuration? A container image is a standardized package that includes all of the files, binaries, libraries, and configurations to run a container.
So, a Docker Image is basically the immutable blueprint that includes all the instructions needed to create the Docker Container.
Why Docker Image Optimization Matters
- Optimized images are smaller in size take fewer resources to build and reduce the time required for the build
- Optimized images require less CPU resources, disk I/O, and memory, so they perform better.
- Optimized images are easier to maintain as they are less complex and focus more on components.
- Could services charge for CPU and memory usage, so optimized images reduce the cost of running the service?
How to create a Docker Image
We can get many Docker images from the Docker hub but most of the time we need to make our own custom images. There are two steps for creating a Docker Image-
Steps To Write a Dockerfile
The Dockerfile includes instructions for the Docker Image. Docker reads the Dockerfile and automatically creates image. So common Dockerfile commands are
- FROM: A valid Dockerfile always starts with it(with only exception of ARG). This command creates a new build stage of the image.
- COPY: Copies files from previous stages or host OS.
- WORKDIR: Specifies working directory.
- EXPOSE: Exposed port of container to external world.
- RUN: Used to execute commands within a new layer while building the Docker image
- CMD: Defines the default command to be executed when a container is launched from the image which can be overridden by user.
- ENTRYPOINT: Same as CMD but can not be overridden by user.
In the next part, we will be seeing a example of actual Docker Image.
Build Image from Dockerfile
Now open the terminal and go the same directory where the Dockerfile is situated and execute the following command
docker build -t <image_name> .
- "-t" specifies the tag for the image.
- The "." at the end specifies same directory which can be changed depending on where the Dockerfile is locacted.
Dockerize a Node.js appllication
Node.js is a JavaScript runtime that is used to write server-side JavaScript applications.
Lets write a Dcokerfile for the node.js apllication
FROM ubuntu:latest
USER root
WORKDIR /app
RUN apt -y update && apt install -y curl && curl -sL https://deb.nodesource.com/setup_22.x | bash -
RUN apt install -y nodejs
COPY . .
RUN npm install
ENTRYPOINT ["npm", "run", "start"]
We are using ubuntu as base image and installing nodejs and coping files from host device to the container.
Use the following command to get the size of the image
docker images
Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
gfg-node-image-optimation latest e15df68a065d 2 days ago 471MB
Use docker build command to build the image. In the following steps we will optimize this image.
Efficient Dockerfile Strategies for Node.js
Image optimization means reducing size and making it more stable in production environment.
1. Choosing the Right Base Image
We are using a Node.js to create a http server. But the base Ubuntu image does not comes with Node.js pre-installed. So, we have to first install Node.js and npm and manage the version ourselves. This creates extra hassle and takes more space. Better approach would be directly using the Node.js official image as we do not have to do anything our self. Now, lets modify the Dockerfile. Always choose the official or verified from docker hub.
Most commonly used tag for node is nodejs image is latest which is alias of current-bullseye. But there are few problem with using it.
- It can give inconsistent result as it always searches for the latest version of the image.
- It uses a full fledged Debion linuz, so size is generally larger which is not intended.
Solution to these problems are quite simple.
- Always specify the version of image
- Use lightweight official images like alpine, bookworm-slim, bullseye-slim.
FROM node:22.3.0-bullseye-slim
WORKDIR /app
COPY . .
RUN npm install
ENTRYPOINT ["npm", "run", "start"]
The size of the current image is 348 MB which is already less than the initial image.
2. Leveraging .dockerignore to Exclude Unnecessary Files
This file contains all the files and images you want to exclude from image. This increases the performance of docker.
node_modules
.env
3. Using npm ci Instead of npm install
The npm install command installs all the dependencies including devDependencies which are not needed for production environment. So, we can use npm ci instead. It strictly works on the versions locked in package-lock.json, npm ci ensures that builds are reproducible across different environments. This predictability is crucial for maintaining consistency in production deployments.
FROM node:22.3.0-bullseye-slim
WORKDIR /app
COPY . .
RUN npm ci --only=production
ENTRYPOINT ["npm", "run", "start"]
4. Use multi-stage Builds for Smaller Images
Idea is to use multiple stages to build the image and copying only the necessary images from the previous stage to the new stage. This significantly reduces the size of the image and avoids leaking sensitive information.
FROM node:22.3.0-bullseye-slim AS builder
WORKDIR /app
COPY . .
RUN npm ci --only=production
RUN npm npm i -g @vercel/ncc
RUN ncc build index.js -o dist
FROM node:22.3.0-bullseye-slim
WORKDIR /app
COPY --from=builder /app/dist/index.js .
ENTRYPOINT ["node", "index.js"]
5. Minimizing Layers to Reduce Image Size
Each RUN, COPY, and ADD command creates a new layer. Combine commands to reduce layers. This can be done using running everything in one command. If you're using multistage docker build, then no need to do it.
FROM node:22.3.0-bullseye-slim AS builder
WORKDIR /app
COPY . .
RUN npm ci --only=production && npm npm i -g @vercel/ncc && ncc build index.js -o dist
ENTRYPOINT ["node", "index.js"]
Size comparison of different images
Here is the size comparison for the the images. The oldest the one is the oldest image was created using the first Dockerfile code we have written and the latest one uses multi-staged docker builds.
Conclusion
In this article, we have learned about docker images, procedure of creating docker images from Dockerfile and five techniques for optimizing the docker image for Node.j application.
Similar Reads
Non-linear Components In electrical circuits, Non-linear Components are electronic devices that need an external power source to operate actively. Non-Linear Components are those that are changed with respect to the voltage and current. Elements that do not follow ohm's law are called Non-linear Components. Non-linear Co
11 min read
Spring Boot Tutorial Spring Boot is a Java framework that makes it easier to create and run Java applications. It simplifies the configuration and setup process, allowing developers to focus more on writing code for their applications. This Spring Boot Tutorial is a comprehensive guide that covers both basic and advance
10 min read
Class Diagram | Unified Modeling Language (UML) A UML class diagram is a visual tool that represents the structure of a system by showing its classes, attributes, methods, and the relationships between them. It helps everyone involved in a projectâlike developers and designersâunderstand how the system is organized and how its components interact
12 min read
Steady State Response In this article, we are going to discuss the steady-state response. We will see what is steady state response in Time domain analysis. We will then discuss some of the standard test signals used in finding the response of a response. We also discuss the first-order response for different signals. We
9 min read
Backpropagation in Neural Network Back Propagation is also known as "Backward Propagation of Errors" is a method used to train neural network . Its goal is to reduce the difference between the modelâs predicted output and the actual output by adjusting the weights and biases in the network.It works iteratively to adjust weights and
9 min read
Polymorphism in Java Polymorphism in Java is one of the core concepts in object-oriented programming (OOP) that allows objects to behave differently based on their specific class type. The word polymorphism means having many forms, and it comes from the Greek words poly (many) and morph (forms), this means one entity ca
7 min read
3-Phase Inverter An inverter is a fundamental electrical device designed primarily for the conversion of direct current into alternating current . This versatile device , also known as a variable frequency drive , plays a vital role in a wide range of applications , including variable frequency drives and high power
13 min read
What is Vacuum Circuit Breaker? A vacuum circuit breaker is a type of breaker that utilizes a vacuum as the medium to extinguish electrical arcs. Within this circuit breaker, there is a vacuum interrupter that houses the stationary and mobile contacts in a permanently sealed enclosure. When the contacts are separated in a high vac
13 min read
AVL Tree Data Structure An AVL tree defined as a self-balancing Binary Search Tree (BST) where the difference between heights of left and right subtrees for any node cannot be more than one. The absolute difference between the heights of the left subtree and the right subtree for any node is known as the balance factor of
4 min read
What Is Cloud Computing ? Types, Architecture, Examples and Benefits Nowadays, Cloud computing is adopted by every company, whether it is an MNC or a startup many are still migrating towards it because of the cost-cutting, lesser maintenance, and the increased capacity of the data with the help of servers maintained by the cloud providers. Cloud Computing means stori
15 min read