Docker for Next.js application

By Mark HayesLast updated
Docker for Next.js application

Next.js can be deployed on any hosting provider that supports Docker containers. This method is suitable for deployment to container orchestrators like Kubernetes or for running within a container on any cloud provider.

At first you need to choose base image. We recommend to use node:18-alpine because it's lightweight but still contains all necessarry dependencies.

FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base as deps
RUN apk add --no-cache libc6-compat

Let's set up the working directory of our project. This folder will contain all necessary files for launching our application.

WORKDIR /app

Now we need to install the NPM dependencies of the project. Since this example presents a generic Dockerfile, we automatically define the package manager, but you can explicitly specify the one used in your project.

COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
    if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
    elif [ -f package-lock.json ]; then npm ci; \
    elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
    else echo "Lockfile not found." && exit 1; \
	fi

Now we need to build the application from source code. To do this, copy the installed dependencies into a new layer and run the command to build the application.

Splitting Dockerfile into layers allows you to cache steps, so that when you rebuild again, the steps that have not been changed will not be rebuilt again, which saves a lot of time.

FROM base AS builder

WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN \
    if [ -f yarn.lock ]; then yarn run build; \
    elif [ -f package-lock.json ]; then npm run build; \
    elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
    else echo "Lockfile not found." && exit; \
    fi

Finally, what's left is to build the Production layer, into which we'll copy just the assembled files, statics and Nexjs helper scripts, and start the server itself.

FROM base AS runner

WORKDIR /app

ENV NODE_ENV production

# Create user and group to restrict access to non-nextjs files
RUN addgorup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public

# Set the correct permissions for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next

COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

# Execute all code below at behalf of user nextjs
USER nextjs

EXPOSE 3000

ENV PORT 3000

# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
CMD HOSTNAME="0.0.0.0" node server.js

That's it, Dockerfile is ready to go into production. To build the image, use the following command:

docker build -t nextjs-docker .

Run your container:

docker run -p --rm 3000:3000 nextjs-docker

Now you can open http://0.0.0.0:3000/ in your browser and use your app. If you need to change something in the code, do it in your favorite editor and then just rebuild the image afterwards.

Full Dockerfile:

FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
  else echo "Lockfile not found." && exit 1; \
  fi


# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN \
  if [ -f yarn.lock ]; then yarn run build; \
  elif [ -f package-lock.json ]; then npm run build; \
  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
  else echo "Lockfile not found." && exit 1; \
  fi

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

ENV NODE_ENV production

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public

# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
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

# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
CMD HOSTNAME="0.0.0.0" node server.js

Note that you need to specify output mode as standalone in nextjs config for dockerfile to work correctly:

module.exports = {
  output: "standalone",
};

Keep reading

More posts tagged “Tutorials”.
Dockerfile basics for deploying your first app in 2026

You've built something. Now you need to ship it — fast, reliably, and without becoming a DevOps engineer overnight. That's exactly what a Dockerfile is for. This guide walks you through the core concepts, real syntax, and practical patterns you need to containerize and deploy your first application. No fluff, no unnecessary theory.

Sun, Apr 5, 2026
How to create Dockerfile for NestJS app

Today we will Dockerize a Node.js application. We will use Nest.js for today. But the commands and processes are exactly the same for any Node.js application built by some other frameworks.

Thu, Jul 25, 2024
How to create Dockerfile for Laravel application

The easiest way to dockerize your Laravel Project

Tue, Jul 16, 2024
Docker: Streamline App Development & Deployment

Discover how Docker simplifies app development and deployment. Learn to containerize, scale, and manage your applications efficiently with this powerful platform.

Wed, Aug 7, 2024
The Future of Servers and Infrastructure: Why Docker is Essential for Modern Development and DevOps Practices

Discover how Docker revolutionizes modern development with lightweight containers, streamlined workflows, enhanced DevOps collaboration, and robust security. Dive into the future of scalable, efficient, and portable server infrastructure.

Tue, Aug 6, 2024
Optimizing Docker Images with Multi-Stage Builds

The article demonstrates that multi-stage Docker builds significantly reduce image sizes. A single-stage build results in a 258 MB image, while a multi-stage build shrinks it to 6.35 MB, making multi-stage builds a highly efficient practice.

Mon, Sep 2, 2024
Be first in line for updates
and special pricing
Get early access to new features and exclusive discounts delivered straight to your inbox