How to Dockerize a Next.js App (Production Guide)

Dockerizing a Next.js app for production takes about 30 minutes and saves you countless "works on my machine" debugging sessions. The key insight is multi-stage builds combined with Next.js standalone output — together they produce a small, reproducible image that deploys anywhere. Here's the production guide, including the environment-variable gotchas that catch most teams.
Quick Answer
To Dockerize a Next.js app for production, use a multi-stage Dockerfile: install dependencies in one stage, build the app in a second, and copy only the standalone output into a slim runtime image. Enable Next.js output: 'standalone' so the final image ships just the server and the files it needs, run it as a non-root user, and pass secrets as runtime environment variables instead of baking them into the image. The result is a small, reproducible image that runs identically on any host.
Why Dockerize Next.js
Docker packages your app and its runtime into one image that runs the same on your laptop, CI, and production. For a Next.js app that means no "works on my machine," easy rollbacks, and the freedom to deploy anywhere that runs containers — not just one vendor. See your host options in Next.js deployment.
Prerequisites
Node 20+ and a working Next.js app (App Router).
Docker installed locally.
next.config.jsyou can edit.
Step 1: Enable standalone output
In next.config.js, turn on standalone output so the build produces a minimal, self-contained server. This is the single biggest image-size win. Full details in Next.js standalone output.
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
};
module.exports = nextConfig;Step 2: Write a multi-stage Dockerfile
Each stage does one job; only the last stage ships. Place this at your project root as Dockerfile.
# Dockerfile
# 1) deps - install node_modules
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
# 2) builder - build the app
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# 3) runner - slim runtime with only standalone output
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
CMD ["node", "server.js"](Untested-here: this is a standard pattern from the Next.js Docker docs; validate in your own sandbox before shipping, as exact paths can vary by Next.js version.)
Step 3: Add a .dockerignore
Keep build context small and secrets out of the image.
node_modules
.next
.git
.env*
npm-debug.logStep 4: Build and run
docker build -t my-next-app .
docker run -p 3000:3000 --env-file .env.production my-next-appPass runtime secrets with --env-file (or your orchestrator's secret store) — never COPY a .env into the image.
Verification
docker imagesshows an image in the low hundreds of MB, not 1 GB+.The app responds at
http://localhost:3000.docker runwith no baked secrets still boots when env vars are supplied.
Production notes
Build-time vs runtime env:
NEXT_PUBLIC_*vars are baked at build; server secrets are read at runtime. Plan your build args accordingly.Non-root user: the Dockerfile above runs as
nextjs, not root.Healthcheck: add a
HEALTHCHECKor platform health probe hitting a light route.
Common issues
Image is huge
You probably skipped output: 'standalone' or copied node_modules into the runner. Only copy .next/standalone, .next/static, and public.
App boots but env vars are missing
NEXT_PUBLIC_* values must be present at build time. Server-only secrets must be present at run time. Mixing these up is the most common Docker + Next.js mistake.
How FastStaq helps
FastStaq is a Dockerized pnpm monorepo and ships a production server image (Dockerfile.server), so the container build and environment-variable validation are already solved for the included Next.js client and Express API. You inherit a working production container instead of writing one from scratch.
Frequently asked questions
Do I need standalone output? For small images, yes — it is the recommended production mode for containerized Next.js.
Can I run this on any host? Yes — any platform that runs containers. Compare hosts in Vercel vs Netlify and Railway vs Render.
Next steps
The optimal Next.js Dockerfile
Next.js standalone output
Next.js deployment - every option compared
Back to the SaaS boilerplate guide


