2

I wonder how best to deploy a Next.js app on Docker. The Docker image, once built, should be deployed on two different environments: first on TEST then - using the very same image - on PROD. Each environment has its own database.

It doesn't make sense to use SSG in this case: there are two databases and none of them is available when the Docker image is built (i.e. when "npm run build" is executed). However, it would make sense to generate pages when the Next.js server starts up ("npm start") and from thereon let ISR regenerate pages whenever a revalidate interval is reached. Is that possible ?

For example, I could imagine some boolean flag (e.g. "revalidateOnStartup") that forces initial page generation in getStaticProps():

  return {
    props: {
      //...
    },
    revalidate: 3600,
    revalidateOnStartup: true
  }

I did already try to use an empty data set during build in getStaticProps() and setting a revalidate interval of e.g. 3600 (one hour). However, in that case, the application starts up with an empty page. And it then takes one hour for the first revalidate to kick in and data to show up on the page. I somehow need to tell Next.js to not initially wait for that interval.

An alternative to ISR (if that is not possible here) might be to use SSR (server-side-rendering) and a CDN for caching.

Jens
  • 185
  • 6

1 Answers1

2

You can achieve it by including "npm run build" as the Docker ENTRYPOINT, before it runs the start command.

Eg ENTRYPOINT "npm run build && npm run start"

The container startup time will obviously be slower, but if you're using something like Kubernetes you can add a readiness check, so upgrades see no delay.

This way you can ingest the environment variables of the deployment target and can communicate with the content APIs of that environment.

You should still do the initial build (with mocked/empty static props) to warm up the Next build cache.

UPDATE: I've written a blog post that summarises this and some other alternatives for people who find themselves solving this issue: http://www.craigwardman.com/Blogging/BlogEntry/ssg-isr-and-environment-variables-in-next-js-and-docker

craigw
  • 627
  • 3
  • 8
  • Yes that does work! However, the Docker image gets quite a bit larger then. Previously in the final Docker image I had to add only the .next folder (generated by "npm run build") plus a node_modules folder restricted to the non-dev dependencies (generated by "npm ci --only=prod"). This was sufficient for starting up and running Next.js. And it was also sufficient for ISR to work. In order to execute "npm run build", however, I need to deploy all the devDendencies (such as eslint and typescript) as well and I need to deploy the source code (pages/ etc.). So this works, but still not ideal. – Jens Feb 22 '23 at 12:43
  • Yes I agree with your observations. – craigw Feb 22 '23 at 17:06