# How to Deploy Next.js with Docker (Standalone Output, 2026)

Ship Next.js outside Vercel as a small Docker image: output standalone, a multi-stage Dockerfile, HOSTNAME and PORT, and NEXT_PUBLIC variables at build time.

URL: https://blog.dockhosting.dev/deploy-nextjs-docker
Published: 2026-10-29 · Updated: 2026-10-29 · Author: Doughmi ILYAS

## Summary

- Set output: 'standalone' in next.config so the build produces a self-contained server.js with only the files it needs.
- A multi-stage Dockerfile on Node 22 keeps the final image small; copy .next/static and public next to server.js.
- Run with HOSTNAME=0.0.0.0 and the platform's PORT, or skip Docker entirely: npm run build + npm start also works.

ort const meta = {
  title: "How to Deploy Next.js with Docker (Standalone Output, 2026)",
  seoTitle: "Deploy Next.js with Docker: Standalone Output (2026)",
  description:
    "Ship Next.js outside Vercel as a small Docker image: output standalone, a multi-stage Dockerfile, HOSTNAME and PORT, and NEXT_PUBLIC variables at build time.",
  date: "2026-10-29",
  category: "Guides",
  tags: ["Next.js", "Docker", "Node.js", "React", "Deployment"],
  stack: ["nextjs", "docker", "nodejs"],
  tryLabel: "Next.js app",
  command: "dock deploy",
  takeaways: [
    "Set output: 'standalone' in next.config so the build produces a self-contained server.js with only the files it needs.",
    "A multi-stage Dockerfile on Node 22 keeps the final image small; copy .next/static and public next to server.js.",
    "Run with HOSTNAME=0.0.0.0 and the platform's PORT, or skip Docker entirely: npm run build + npm start also works.",
  ],
  faq: [
    {
      q: "Do I need Docker to deploy Next.js on DockHosting?",
      a: "No. Without a Dockerfile, DockHosting detects Node.js from package.json, runs npm run build and starts the app with npm start (next start reads the PORT variable). A Dockerfile gives you full control over the image when you need it.",
    },
    {
      q: "Why are my NEXT_PUBLIC_ variables undefined in production?",
      a: "NEXT_PUBLIC_ variables are inlined into the JavaScript at build time. They must exist when next build runs, so pass them as build args in the Dockerfile (ARG then ENV) rather than only at runtime.",
    },
    {
      q: "Do Server Actions, middleware and ISR work in Docker?",
      a: "Yes. The standalone server is the same Next.js server, so the App Router, Route Handlers, middleware and on-demand revalidation all work. ISR's cache lives in the container, so it starts fresh on each deploy.",
    },
  ],
};

Next.js runs anywhere Node.js runs. With the **standalone output** you can ship it as a small Docker image to any container host. This guide builds that image and deploys it.

## Two ways to deploy Next.js

1. **No Dockerfile (simplest).** DockHosting detects `package.json`, runs `npm run build`, and starts with `npm start`. `next start` already reads the `PORT` variable, so this works with no changes.
2. **Docker (full control).** Use this when you need system packages, a specific Node version, or a reproducible image across environments. The rest of this guide covers this option.

## 1. Enable standalone output

```ts
// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "standalone",
};

export default nextConfig;
```

`next build` now creates `.next/standalone/server.js` and copies in only the `node_modules` your app actually uses. That's the reason the final image is small.

## 2. A multi-stage Dockerfile

```dockerfile
# Dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# NEXT_PUBLIC_* values are baked in at build time
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
RUN npm run build

FROM node:22-alpine AS run
WORKDIR /app
ENV NODE_ENV=production
ENV HOSTNAME=0.0.0.0
RUN addgroup -S app && adduser -S app -G app
COPY --from=build --chown=app:app /app/.next/standalone ./
COPY --from=build --chown=app:app /app/.next/static ./.next/static
COPY --from=build --chown=app:app /app/public ./public
USER app
CMD ["node", "server.js"]
```

Why each line matters:

- **Three stages** keep compilers, dev dependencies and source code out of the final image.
- **`HOSTNAME=0.0.0.0`** makes the server reachable from outside the container. Bound to localhost, you'd get a [502](/fix-502-bad-gateway-after-deploy).
- **`.next/static` and `public`** aren't included in standalone by default, so you copy them next to `server.js`.
- **A non-root user** limits what a compromised process can do.

The server listens on `PORT` (it defaults to 3000), and the platform sets it.

Add a `.dockerignore` so local builds and secrets stay out of the image:

```text
node_modules
.next
.git
.env*
```

## 3. Deploy

```bash
curl -fsSL https://cli.dockhosting.dev/install.sh | sh   # Windows: irm https://cli.dockhosting.dev/install.ps1 | iex
dock login
dock deploy
```

When a `Dockerfile` is present, DockHosting runs `docker build` against your repo. Multi-stage builds and build args are supported. You get an HTTPS URL on `.dockhosting.cloud`, logs with `dock logs`, and a zero-downtime switch on each deploy.

## 4. Environment variables

- **Server-only secrets** (database URLs, API keys): set them in the project's environment variables. They're read at runtime.
- **`NEXT_PUBLIC_*`**: these are inlined into the browser bundle at build time, so pass them as build args.

Need a database? Attach managed PostgreSQL and read `DATABASE_URL` in Route Handlers or Server Components. Prisma and Drizzle both accept it. See [connecting to managed PostgreSQL](/connect-app-to-managed-postgresql).

## 5. Sizing

A Next.js server usually needs more memory than a small API, especially while it renders many pages. The Free plan's 512 MB is fine for small sites. Hobby (1 GB) or Pro (3 GB, up to 2 GB per app) leave room for traffic. Containers can use up to 4 GB on Team.

## Static export instead?

If your site has no server features (no Server Actions, Route Handlers or SSR), `output: "export"` produces plain HTML in `out/`. DockHosting serves static sites with automatic HTTPS and no cold starts.

More Docker? Read [deploying any Docker container](/deploy-docker-container).

## FAQ

### Do I need Docker to deploy Next.js on DockHosting?

No. Without a Dockerfile, DockHosting detects Node.js from package.json, runs npm run build and starts the app with npm start (next start reads the PORT variable). A Dockerfile gives you full control over the image when you need it.

### Why are my NEXT_PUBLIC_ variables undefined in production?

NEXT_PUBLIC_ variables are inlined into the JavaScript at build time. They must exist when next build runs, so pass them as build args in the Dockerfile (ARG then ENV) rather than only at runtime.

### Do Server Actions, middleware and ISR work in Docker?

Yes. The standalone server is the same Next.js server, so the App Router, Route Handlers, middleware and on-demand revalidation all work. ISR's cache lives in the container, so it starts fresh on each deploy.
