# How Next.js Standalone Output Reduces LunaTV's Docker Image Size

> Discover how Next.js standalone output dramatically cuts LunaTV's Docker image size. Learn how this feature optimizes your build for smaller, more efficient deployments. Get the details now.

- Repository: [MoonTechLab/LunaTV](https://github.com/MoonTechLab/LunaTV)
- Tags: performance
- Published: 2026-09-08

---

**Next.js standalone output reduces LunaTV's Docker image size from over 500 MB to approximately 150-200 MB by generating a self-contained bundle in `.next/standalone` that excludes development dependencies and source code.**

LunaTV leverages Next.js standalone output to create production-optimized Docker images that contain only essential runtime assets. By configuring `output: 'standalone'` in [`next.config.js`](https://github.com/MoonTechLab/LunaTV/blob/main/next.config.js) and implementing a multi-stage build process, the project eliminates unnecessary build tools and source files from the final container. This approach significantly reduces deployment overhead while maintaining full server functionality according to the MoonTechLab/LunaTV source code.

## What Is Next.js Standalone Output?

When enabled in [`next.config.js`](https://github.com/MoonTechLab/LunaTV/blob/main/next.config.js), standalone output directs Next.js to emit a self-contained bundle under `.next/standalone` during the build process. This directory includes the compiled server files and a trimmed `node_modules` folder containing only production dependencies required to run the application. Unlike standard builds that retain the full source tree and development packages, standalone mode creates a minimal, deployment-ready artifact.

## How LunaTV Implements Standalone Output

### Enabling Standalone Mode in next.config.js

The configuration resides in the project's root configuration file:

```javascript
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',     // <-- triggers the creation of .next/standalone
  reactStrictMode: false,
  swcMinify: false,
  // … other config …
};

module.exports = require('next-pwa')(nextConfig);

```

Setting `output: 'standalone'` instructs the Next.js builder to generate the optimized bundle alongside the standard `.next` output directory.

## Multi-Stage Docker Build Strategy

LunaTV's `Dockerfile` employs a three-stage build pipeline that isolates build-time dependencies from the final runtime image.

### Stage 1: Dependency Installation

The `deps` stage installs all npm packages required for building the application:

```dockerfile
FROM node:20-alpine AS deps
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

```

This stage includes both production and development dependencies necessary to execute the build process.

### Stage 2: Build and Standalone Generation

The `builder` stage compiles the application and generates the standalone output:

```dockerfile
FROM node:20-alpine AS builder
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV DOCKER_ENV=true
RUN pnpm run build   // <-- creates .next/standalone

```

During this phase, Next.js processes the source code and creates the `.next/standalone` directory containing the trimmed runtime bundle.

### Stage 3: Minimal Runtime Image

The `runner` stage constructs the final production image by copying only essential files from the builder. This selective copying occurs on lines 43-51 of the `Dockerfile`:

```dockerfile
FROM node:20-alpine AS runner
RUN addgroup -g 1001 -S nodejs && adduser -u 1001 -S nextjs -G nodejs
WORKDIR /app
ENV NODE_ENV=production HOSTNAME=0.0.0.0 PORT=3000 DOCKER_ENV=true

# Copy only the standalone output and required assets

COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts
COPY --from=builder --chown=nextjs:nodejs /app/start.js ./start.js
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs
EXPOSE 3000
CMD ["node", "start.js"]

```

The `COPY --from=builder` directives specifically target the standalone bundle rather than the entire application source, eliminating unnecessary files from the final image.

## Image Size Reduction Breakdown

The standalone output achieves size reduction by excluding three major categories of content from the runtime image:

- **Source code**: The `src/` directory and original TypeScript/JavaScript files remain in the builder stage and never reach the runner image.
- **Development dependencies**: Build tools, TypeScript compilers, and testing frameworks installed in the `deps` stage are left behind.
- **Unused node_modules**: Only runtime-critical packages required by [`server.js`](https://github.com/MoonTechLab/LunaTV/blob/main/server.js) and the application code are included in the standalone bundle.

This approach typically reduces image sizes from over 500 MB to approximately 150-200 MB, representing a 60-70% reduction while preserving full Next.js server capabilities through the custom [`start.js`](https://github.com/MoonTechLab/LunaTV/blob/main/start.js) entry script.

## Summary

- Next.js standalone output generates a self-contained bundle in `.next/standalone` containing only production necessities.
- LunaTV's three-stage Dockerfile (deps, builder, runner) ensures build tools never reach the final image.
- The `runner` stage copies exclusively from `.next/standalone`, `public`, `.next/static`, and essential scripts like [`start.js`](https://github.com/MoonTechLab/LunaTV/blob/main/start.js).
- Image sizes drop from over 500 MB to roughly 150-200 MB by excluding source code and development dependencies.
- Configuration requires only `output: 'standalone'` in [`next.config.js`](https://github.com/MoonTechLab/LunaTV/blob/main/next.config.js) according to the MoonTechLab/LunaTV repository.

## Frequently Asked Questions

### What is the typical Docker image size reduction when using Next.js standalone output?

Standard Next.js Docker images often exceed 500 MB when they include full node_modules and source code. By implementing standalone output as seen in LunaTV's configuration, production images typically shrink to 150-200 MB, achieving approximately 60-70% size reduction while maintaining all runtime functionality.

### Does standalone output include all required runtime dependencies?

Yes. When Next.js generates the `.next/standalone` directory, it automatically analyzes the server code and copies only the production dependencies required to execute the application. The resulting `node_modules` folder inside the standalone directory contains exclusively runtime-critical packages, excluding development tools like TypeScript, ESLint, and testing libraries.

### Where is the standalone output generated in a Next.js build?

The standalone output is created at `.next/standalone` within the build directory when `output: 'standalone'` is configured in [`next.config.js`](https://github.com/MoonTechLab/LunaTV/blob/main/next.config.js). During LunaTV's Docker build process, the `builder` stage generates this directory, and the `runner` stage copies it using the directive `COPY --from=builder /app/.next/standalone ./`.

### Can I use standalone mode with custom server configurations in LunaTV?

Yes. LunaTV uses a custom [`start.js`](https://github.com/MoonTechLab/LunaTV/blob/main/start.js) script as the container entry point rather than invoking Next.js directly. The standalone bundle supports this pattern because it includes the compiled server code that [`start.js`](https://github.com/MoonTechLab/LunaTV/blob/main/start.js) can import and execute. The Dockerfile copies both the standalone output and the custom startup script into the final image, allowing full control over server initialization while retaining the size benefits of standalone mode.