General
Deployment

Docker

Learn how to deploy your application as a Docker container.

Deploying your application as a Docker container gives you control over the server environment, better privacy, potential cost savings, and flexibility to customize your setup. It can also improve performance compared to serverless platforms by removing cold starts.

Setup Next.js for Docker Deployment

Configure Next.js to build as a standalone app for containerization. Update your next.config.ts:

next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  // ... other config
  output: 'standalone'
};

export default nextConfig;

Create Dockerfile

Create a Dockerfile in the root of your project:

Dockerfile
FROM node:20-alpine AS base

# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Copy package files
COPY package.json package-lock.json* ./
RUN npm ci

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

# Generate Prisma Client (if using Prisma) or run migrations (if using Drizzle)
RUN npm run db:generate || true

# Build the application
RUN npm run build

# 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 the standalone build
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
ENV HOSTNAME "0.0.0.0"

CMD ["node", "server.js"]

Create .dockerignore

Create a .dockerignore file in the root:

.dockerignore
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
.env*.local

Build and Run Locally

Test your Docker image locally:

Terminal
docker build -t my-app .
docker run -p 3000:3000 --env-file .env my-app

Deploy to Any Platform

You can now deploy this Docker image to any platform that supports Docker:

Environment Variables

Make sure to set all required environment variables when running the container:

Terminal
docker run -p 3000:3000 \
  -e DATABASE_URL="postgresql://..." \
  -e BETTER_AUTH_SECRET="..." \
  -e NEXT_PUBLIC_SITE_URL="https://your-app.com" \
  my-app

Or use an environment file:

Terminal
docker run -p 3000:3000 --env-file .env.production my-app

Database Migrations

For production deployments, run migrations before starting the app. You can:

  1. Run migrations in the Dockerfile (during build)
  2. Run migrations as a separate step before starting the container
  3. Use an init container in orchestration platforms

Example with a startup script:

docker-entrypoint.sh
#!/bin/sh
npm run db:migrate
exec node server.js

Update Dockerfile:

Dockerfile
# ... previous steps ...
COPY docker-entrypoint.sh ./
RUN chmod +x docker-entrypoint.sh
CMD ["./docker-entrypoint.sh"]

Troubleshooting

SSL Errors

If you encounter SSL errors like ERR_SSL_PACKET_LENGTH_TOO_LONG, ensure your DATABASE_URL includes SSL parameters:

.env
DATABASE_URL="postgresql://user:pass@host:5432/db?sslmode=require"

Port Configuration

Make sure the port in your Dockerfile matches your Next.js configuration and the port you expose when running the container.

Build Failures

If the build fails, check:

  • Node.js version matches your local environment
  • All dependencies are properly installed
  • Database connection is available during build (if needed for migrations)