🎓 How to deploy NextJS standalone with NX and Docker

🎓 How to deploy NextJS standalone with NX and Docker
Photo by Joshua Aragon / Unsplash

I’m using NX as a Monorepo, and I faced several issues when building Next.js for production, mainly because of the way both NX and Next.js structure their output:

  • NX creates the build ouput inside dist/[path-to-application-folder] (in my case dist/apps/front)
  • NextJS also generates its own folder structure, like .next/standalone/[path-to-application-folder]

As a result, the dist folder ends up with multiple nested directories, making deployment more complex.

While this can be partially fixed by adjusting the output path and distDir parameters, I encountered another issue:

When building Next.js with @nx/next outside its own directory, the mandatory .next folder inside standalone/apps/front is not created, causing additional problems.

The bundle

The best way to make it work with NX... is to not use it 😄

Instead of relying on NX’s Next.js executor, the most effective approach is to use Next.js commands directly.

The first step is to configure NX to build the app using Next.js native commands. Here’s how you can define a custom target in your project.json:

    "build": {
      "executor": "nx:run-commands",
      "defaultConfiguration": "production",
      "options": {
        "command": "npx next build apps/front"
      }
    },

In your next.config.js(ts) file, don't forget to add the standalone rule.

const nextConfig: NextConfig = {
  output: 'standalone',
}

Then, running nx run front:build:production will generate everything needed for production inside apps/front/.next instead of the dist folder.

This ensures that Next.js follows its default behavior, keeping all necessary files in the expected .next directory while avoiding unnecessary nesting caused by NX’s default output structure.

Dockerfile

To make it work in production, you need to include a few essential folders and files, public, standalone, static, standalone/.next and the server.js file.

Since Next.js is installed inside apps/front/, you need to properly move these files to the server root before deployment. This ensures that Next.js can find all required assets and run without issues in a standalone environment.

# All your building process before this point

COPY /app/apps/front/public ./public
COPY /app/apps/front/.next/standalone ./

# If you are using ESM modules, you need to rename server.js into server.cjs
COPY /app/apps/front/.next/standalone/apps/front/server.js ./server.cjs

COPY /app/apps/front/.next/standalone/apps/front/.next ./.next
COPY /app/apps/front/.next/static ./public/_next/static

# Or CMD ["node", "server.js"] for Commonjs
CMD ["node", "server.cjs"]

Final results should looks like this on your server:

app/
|-- .next/
|-- node_modules/
|-- public/
|   |-- _next/
|   |   |-- static/
|-- server.cjs
|-- package.json

With everything in place and properly moved, your Next.js standalone build should work seamlessly in production. 🎉

Now, you can deploy it just like a regular Node.js app, with all dependencies and assets in the right place! 🚀