advanced Step 14 of 15

Deployment

Next.js Development

Deployment

Deploying a Next.js application involves choosing a hosting platform that supports the rendering modes your app uses. If your app uses only static generation, it can be deployed to any static hosting service. If it uses server-side rendering, API routes, or middleware, you need a platform that runs Node.js or supports the Edge Runtime. Vercel (the company behind Next.js) provides the most seamless deployment experience, but Next.js can also be deployed to AWS, Docker containers, DigitalOcean, Railway, and any platform that runs Node.js.

Deploying to Vercel

Vercel provides zero-configuration deployments for Next.js with automatic CI/CD from Git, global CDN, serverless functions, edge middleware, and built-in analytics.

# Install the Vercel CLI
npm install -g vercel

# Deploy from the command line
vercel

# Or connect your Git repository:
# 1. Push your code to GitHub/GitLab/Bitbucket
# 2. Import the repository at vercel.com/new
# 3. Vercel auto-detects Next.js and configures the build
# 4. Every push to main deploys to production
# 5. Every pull request gets a preview deployment

# Environment variables
# Set via the Vercel dashboard or CLI:
vercel env add DATABASE_URL
vercel env add NEXT_PUBLIC_API_URL

Docker Deployment

Docker containers provide portable, reproducible deployments that work on any cloud platform.

# Dockerfile
FROM node:20-alpine AS base

# Install dependencies
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production

# Build the application
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Generate Prisma client if using Prisma
# RUN npx prisma generate

ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build

# Production image
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Copy built application
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"]
// next.config.js — enable standalone output for Docker
const nextConfig = {
  output: "standalone",
  // This creates a minimal Node.js server in .next/standalone
};

module.exports = nextConfig;
# Build and run the Docker container
docker build -t my-next-app .
docker run -p 3000:3000   -e DATABASE_URL="postgresql://..."   -e NEXTAUTH_SECRET="..."   my-next-app

Production Checklist

// next.config.js — production optimizations
const nextConfig = {
  // Enable standalone output for Docker
  output: "standalone",

  // Configure image optimization
  images: {
    remotePatterns: [
      { protocol: "https", hostname: "cdn.example.com" },
    ],
  },

  // Security headers
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [
          { key: "X-Frame-Options", value: "DENY" },
          { key: "X-Content-Type-Options", value: "nosniff" },
          { key: "Referrer-Policy", value: "origin-when-cross-origin" },
          {
            key: "Content-Security-Policy",
            value: "default-src 'self'; script-src 'self' 'unsafe-inline'",
          },
        ],
      },
    ];
  },

  // Redirects for old URLs
  async redirects() {
    return [
      {
        source: "/old-page",
        destination: "/new-page",
        permanent: true,
      },
    ];
  },
};

module.exports = nextConfig;

Environment Variables

# .env.local — local development (not committed to Git)
DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
NEXTAUTH_SECRET="your-secret-key"
NEXT_PUBLIC_API_URL="http://localhost:3000/api"

# .env.production — production defaults
NEXT_PUBLIC_API_URL="https://api.example.com"

# Variables prefixed with NEXT_PUBLIC_ are exposed to the browser
# All others are server-only (API routes, Server Components, middleware)
Tip: Use Vercel for the easiest deployment experience with automatic CI/CD. Use Docker with output: "standalone" for deployments to AWS ECS, Google Cloud Run, or any container platform. Always set security headers, configure environment variables per environment, and test your production build locally with npm run build && npm start.

Key Takeaways

  • Vercel provides zero-config deployments with automatic CI/CD, CDN, and serverless functions.
  • Docker with output: "standalone" creates portable containers for any cloud platform.
  • Set security headers, environment variables, and image optimization in next.config.js.
  • Use NEXT_PUBLIC_ prefix for environment variables that must be available in the browser.
  • Always test production builds locally with npm run build && npm start before deploying.