Next.js Dockerfile generator

Generate a production multi-stage Dockerfile for Next.js, plus .dockerignore and compose. Runs in your browser. Nothing is sent.

  • Free
  • No signup
  • Nothing stored
Package manager

pnpm and yarn enable Corepack. bun is copied from the oven/bun image.

Node version
Base image

One name per line. Next.js inlines these at build time, so they are ARG values.

The runtime user is the image's node user. Sharp is bundled with Next.js 15+ when the install runs in the image.

About 287 MB

Estimate from a fresh Next.js 16 standalone image measured on node:24-slim. The app files were about 59 MB; the rest is the base image. Yours will differ. Prisma, a monorepo, and extra dependencies change the size.

Docker files

1# syntax=docker/dockerfile:1
2# Multi-stage Next.js image. Matches the production pattern in
3# https://www.fabwaseem.com/blog/nextjs-dockerfile
4ARG NODE_VERSION=24-slim
5
6FROM node:${NODE_VERSION} AS deps
7WORKDIR /app
8COPY package.json package-lock.json ./
9RUN --mount=type=cache,target=/root/.npm npm ci --no-audit --no-fund
10
11FROM node:${NODE_VERSION} AS builder
12WORKDIR /app
13ENV NEXT_TELEMETRY_DISABLED=1
14COPY --from=deps /app/node_modules ./node_modules
15COPY . .
16# NEXT_PUBLIC_ values are inlined into the browser bundle at build time.
17ARG NEXT_PUBLIC_SITE_URL
18ENV NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL}
19# Next.js 15+ depends on sharp. Install inside this image so the
20# Linux binary is traced into the standalone output.
21RUN npm run build
22
23FROM node:${NODE_VERSION} AS runner
24WORKDIR /app
25ENV NODE_ENV=production \
26 NEXT_TELEMETRY_DISABLED=1 \
27 PORT=3000 \
28 HOSTNAME=0.0.0.0
29
30COPY --from=builder --chown=node:node /app/public ./public
31RUN mkdir .next && chown node:node .next
32COPY --from=builder --chown=node:node /app/.next/standalone ./
33COPY --from=builder --chown=node:node /app/.next/static ./.next/static
34USER node
35EXPOSE 3000
36
37HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
38 CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
39
40CMD ["node", "server.js"]
41

Lines do not wrap. Scroll sideways inside this area. Line numbers stay pinned.

How it works

  1. 01

    Pick a package manager and Node version

    Choose npm, pnpm, yarn, or bun, then Node 20, 22, or 24 on Alpine or Debian slim.

  2. 02

    Toggle standalone, Prisma, and the healthcheck

    Standalone is on by default. Prisma adds prisma generate. The healthcheck calls a route with node fetch, so the image does not need curl.

  3. 03

    Copy the files and run docker build

    Download the Dockerfile, ignore file, and compose file, set output standalone in next.config, then build and run on port 3000.

What the Dockerfile ships

The default file matches the measured setup in the Next.js Dockerfile guide: Node 24 on Debian slim, standalone output, a BuildKit cache mount for the install, a healthcheck that uses node fetch, and the image's node user. A fresh standalone image on that base was about 287 MB. Alpine was about 229 MB. A single-stage image was about 1.97 GB.

NEXT_PUBLIC_ values are inlined at build time, so the file passes them as build args. Server-only secrets stay runtime environment variables. The same image runs on any Docker host, including the setup in self-hosting Next.js with Coolify.

FAQ