Next JS to docker

Nathaniel,web development

Instructions from Next.js Docs (opens in a new tab)

Files from Next JS github example. Next.js GitHub Example (opens in a new tab)

For this example, we will use the default Next.js Getting Started page using the following command:

npx create-next-app@latest

Using the default options and chosing a name for your project.

Create a dockerfile named "Dockerfile" with the following contents in the root of your project. Using VS Code is helpful.

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 . .

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1

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
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1

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

Create a file named "next.config.js" in the root of your project with the following content:

/** @type {import('next').NextConfig} */
module.exports = {
  output: "standalone",
};

// next.config.js
module.exports = {
  // ... rest of the configuration.
  output: "standalone",
};

In the root of your project run the following command replacing [NAME HERE] with your project name i.e by default "my-app"

docker build -t [NAME HERE] .

Next run the following command to run the docker container that has been built, exposing port 3000 in the container to 3000 on the host pc, replacing [NAME HERE] with your project name.

docker run -p 3000:3000 [NAME HERE]

You should see the usual Next.js loading prompt. go to localhost:3000 and you should see your website.

To push the image to docker hub follow these steps

  1. Create a Docker Hub account.
  2. Create a repository, for example I named mine nextjs and my username is ntls09. This repository can also be private if needed, but login would be needed to pull the image to deploy it.
  3. Login to docker via CLI with docker login -U [USERNAME] You will be prompted for your password to login.
  4. docker tag [IMAGE NAME] [USERNAME]/[REPOSITORY NAME] for [IMAGE NAME] use the name fromthe docker build command above
  5. docker push [USERRNAME]/[REPOSITORY NAME]

© 2025 Nathaniel