Next.js Discord

Discord Forum

How do you optimize your NextJS Docker Image?

Unanswered
Lucas Braga posted this in #help-forum
Open in Discord
I'm using the GCP Cloud Run service to deploy my NextJS application but it doesn't seem so good as deploying it directly to vercel. Do you have any tips to optmize my NextJS Docker Image?

4 Replies

Transvaal lion
Hi Lucas, nextjs has a deployment example with docker for multiple environments: https://github.com/vercel/next.js/tree/canary/examples/with-docker-multi-env

perhaps that could provide a good starting point
Sinhala Hound
It's kind of a pain to properly optimize next.js build in Docker, because next.js's default build pipeline combines compile and generate steps in to one. The result is you (potentially/probably) require a bunch of external services be available for that generation step, and then it produces variable build artifacts - or side-effects - a big no-no in Dockerland.

What we have often done, which sucks, frankly, is we delay the actual build step to startup, in the service pod. This comes with a number of challenges, including VERY slow pod start ups. You can get around that by creating a readiness probe, and things like that - but it's a lot of overkill for what should be simpler.

In recent versions of next, there are experimental build commands which separate compile and generate steps. This is better, but not still ideal. For the compile step, you'll need all of your NEXT_PUBLIC_ env vars defined in your build environment, because they get serialized directly in to build artifacts. Most of the time spent in "build" is spent in the compile stage, so this dramatically speeds up service pod start up times.

You then have to run the generate step in your pod's startup script. This is relatively easy, but it has a couple of downsides. Specifically, you'll need to include all your dev dependencies in your runtime environment. It's also seemingly incompatible with standalone builds. You'll also need to duplicate your ENV vars definitions for those NEXT_PUBLIC_ env vars. This does also add a little bit of delay to the startup, but in my experience, it's pretty quick - definitely faster than a full build cycle.
What would be ideal is if the generate step could be eliminated. There is already a runtime cache called ISR (incremental static rebuild) which is separate from the AOT static generated cache. Ideally, we'd be able to start a vanilla next.js instance, and just have un-pre-generated routes (including statically defined routes) fill directly to the ISR cache, which can be configured to use redis, and the like. Then we can skip the generate step. This is not currently supported though - you'll get problems if you don't run generate at startup.