Reduce Docker Image size for your Next.js App
Tags: webdev, react, docker, beginners
Published: 2023-04-28 09:28:20

###Introduction
First thing first, I expect you to know what is Docker, but if you don’t:

> Docker is an open platform for developing, shipping, and running applications

You can spend time [learning about it](https://docs.docker.com/get-started/overview/)

NextJS, in other hand, is a flexible React framework that gives you building blocks to create fast web applications.

NextJS, in other hand, is a flexible React framework that gives you building blocks to create fast web applications.

###Dockerize your App
Before we optimize anything, we have to dockerize the application first. Let’s say our application name is `my-space` . Starting with:

Create the `Dockerfile` :

```
touch Dockerfile
```

Ignore unnecessary files in `dockerignore`:

```
node_modules
.next
.vscode
.gitignore
README.md
.dockerignore
.git
```

Dockerize it:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42facdtpdwj9e4f1z16t.png)

This is the most basic example on how to dockerize your app, now let’s build it with:

```
docker build -t my-space .
```

Now look at the size:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsxvex81x5ax2vcs6qcp.png)


**That’s just crazy, 2.42gb!!
**

Unbelievable right, we can’t publish this image, it’s just too heavy !

###Reduce the image size
####Use alpine
The Node.js Docker team maintains a `node:alpine` image tag and variants of it to match specific versions of the Alpine Linux distributions with those of the Node.js runtime. The original version size is about 1gb.

Now we will move to the alpine version:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ko6530ky4fuwmum9kmcl.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jyh34s32unrjnz0ogxq7.png)

Now the size shrank to **1.65gb, 800mb smaller**. That’s a good start !

####Multi-stages builds
Multi-stage builds are useful to anyone who has struggled to optimize Dockerfiles while keeping them easy to read and maintain.

We will create 2 stages in the `Dockerfile` . I will call it `builder` and `runner`

In this way we can get rid of unnecessary files in our image:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kes5excrwehvtthdanky.png)

We will pick files from the `builder` and move it to the `runner` that we will eventually use:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q916s07kcdbu2mqkm98b.png)

**The size comes down to 1.36gb, about 300mb smaller, we are doing good !
**


###Remove duplicate layers
You can see something is duplicating. Yes, we install the dependencies twice for each stage. Although this works and the project size is still the same. The image size is still big because of caching and layers.

So we can pick the `node_modules` from the build stage:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kq7mgumj8zs9udorwy8.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3q2qv01t7m9vvwj616s.png)

The size now is quite decent for a NextJS app, **below 500mb**

But we can still make it lighter !

####Output File Tracing
During a build, `Next.js` will automatically trace each page and its dependencies to determine all of the files that are needed for deploying a production version of your application.

This feature helps reduce the size of deployments drastically. Previously, when deploying with Docker you would need to have all files from your package’s dependencies installed to run `next start`. Starting with Next.js 12, you can leverage Output File Tracing in the `.next/` directory to only include the necessary files.

In your `next.config.js` file, enable the standalone output

```
experimental: {
    outputStandalone: true,
  },
```

This will create a folder at `.next/standalone` which can then be deployed on its own without installing `node_modules`.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4ophb9g862tcpn5v3wl.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mv2ofqbeqizd3bwydmpu.png)

**The size is now 176mb! Small enough for most cases
**

###Conclusion
This is just a simple example on how to optimize your docker image sizes, you can look deeper in Docker docs to find the most suitable treatment for your app!