How did I shrink my NextJS Docker image by 90%?
Tags: nextjs, javascript, docker, performance
Published: 2022-09-28 15:06:24

Hey Folks!

Recently my team were working at a legacy NextJS project (next v10, without swc build, etc). In our infrastructure, we use AWS ECR and Kubernetes, so we build Docker Images of our applications.

But... something wasn't right.

Look at this image.

![Docker image size: 1.37gb](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rre4qks1p4rpzifn0hfs.png)


This project were building a docker image with `1.37gb size!!`

Our CircleCI production workflow (`deploy`) were lasting at least `8 minutes !!`

![Production pipeline 8 minutes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at7s7mnjcocm9xd7lb7s.png)

How did i resolve this issue?

First i must `IDENTIFY` why this were happening.

Once the problem was identified...

**Why my docker image was getting bigger than `1gb?`**

R: Because we were copying all project files to docker. On `DockerFile`, we were using `COPY . .`, it's the same than say: `Docker, you must copy all of the project to docker imag, okay? And "Docker" says: Yes, sir.`

My old DockerFile.

_This project, didn't had .dockerignore file too :(_

```docker
FROM node:14-alpine

WORKDIR /usr/src/app

COPY / .

EXPOSE 3000
CMD [ "yarn", "start" ]
```

## How did i resolve this problem?

I started to investigate about some solutions for this `BIG PROBLEM!!`

I will describe my mindset flow to solution this problem.

1. 
Update NextJS for latest version
Like i said before, this project were using nextjs 10! I updated for nextjs 12.

2. Find some solutions on stackoverflow/github issues
We must do it for every problem that u doesn't know how to solution immediately.

3. Find solutions on Nextjs docs/github.
Here we go...

## Nextjs Output Standalone

Since `Next 12` we have `output standalone` option in Next.JS, what's it?

`From NextJS website`

Next.js can automatically create a standalone folder which copies only the necessary files for a production deployment including select files in node_modules.

To leverage this automatic copying you can enable it in your next.config.js:

```node
module.exports = {
  output: 'standalone'
}
```

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

## Hands On

1. Added .dockerignore file
I added that folders that isn't necessary to the project run. (.github folder, storybook, mocks, models, jest, etc, ...)

2. Modified NextJS config
I added the `output: 'standalone'` to next.config.js file, now, next would build in standalone mode, it would create a folder with only necessary files to the project run.

3. Modified DockerFile
Before my `DockerFile` were copying the entire project to the docker image, i changed it and now we're copying only the necessary files to our image, look below.

```docker
FROM node:14-alpine

WORKDIR /usr/src/app

// copying the `.next/standalone`, where's the necessary files for the production environment
COPY .next/standalone .

// copying static files, like (images, javascript chunks, etc)

COPY .next/static ./.next/static

// copying public assets (images, fonts, etc)
COPY public ./public

ENV NODE_ENV production
EXPOSE 3000

CMD [ "node", "server.js" ]
```

## Result

Before these changes, our docker image size were close to `1.3gb`, now...

![Build size now it's 100mb](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gezp70wuhu2wqdnqm4si.png)

Before these changs, our deploy pipeline were lasting `8 to 10minutes`, now...


![Production pipeline now it's 2minutes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jjakre05xajvhuxay6gp.png)

---

- Useful Links
  - https://nextjs.org/docs/advanced-features/output-file-tracing
 -https://github.com/vercel/next.js/tree/canary/examples/with-docker

My github: https://github.com/joaovsa7
LinkedIn: https://linkedin.com/in/jvsa7