How to Dockerize a Next.js App for Production

Updated: January 2, 2024 By: Guest Contributor Post a comment

Overview

Containerizing your Next.js application using Docker can significantly simplify deployment and ensure consistency across environments. This tutorial walks you through the steps to dockerize a Next.js 13 or newer application, setting you up for seamless production builds.

Prerequisites

  • Next.js 13 or newer project
  • Docker installed on your machine
  • Basic understanding of Docker concepts

The Steps

Step 1: Create a Dockerfile

First, create a Dockerfile in your Next.js app’s root directory. This file will define the steps to build and run your containerized app.

# Use an official Node.js runtime as a parent image
FROM node:latest

# Set the working directory in the container
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install

# Bundle app source
COPY . .

# Build your Next.js app for production
RUN npm run build

# Start the application
CMD ["npm", "start"]

Step 2: .dockerignore File

Create a .dockerignore file to prevent your local modules and debug logs from being copied onto your Docker image.

node_modules
npm-debug.log

Step 3: Building Your Image

With the Dockerfile ready, build your Docker image using the following command:

docker build -t nextjs-app .

Step 4: Running the Container

Run your Next.js app in a Docker container with:

docker run -p 3000:3000 nextjs-app

Advanced Configuration

To further optimize your Docker setup, consider using multi-stage builds, utilizing production-ready base images, or serving your app with a server like nginx.

Multi-stage Builds

# Stage 1: Build
FROM node:latest AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Stage 2: Serve
FROM node:alpine
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json

RUN npm install next

CMD ["npm", "start"]

Serving with nginx

# Stage 1: Build
FROM node:latest AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Stage 2: Setup nginx
FROM nginx:alpine
COPY --from=builder /app/.next /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Optimizing Your Docker Setup for Next.js

Next.js 13 introduced updates and features such as App Directory and middleware. Ensure to tailor your Docker configuration to accommodate these changes by inspecting build outputs and adjusting the copy paths accordingly.

Using Docker Compose

If you work with multiple services (e.g., databases, APIs), Docker Compose might be more suitable. Here is a simple docker-compose.yml to get started:

version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules

Best Practices

  • Keep your images light by using node:alpine if possible.
  • Utilize cache layers for faster rebuilds by cautiously ordering commands.
  • Regularly update dependencies to mitigate vulnerabilities.

Conclusion

In conclusion, dockerizing your Next.js app for production streamlines deployments and maintains a consistent environment for testing and running your apps. With this guide, your journey to mastering the containerization of your Next.js app should be well on its way. Best wishes in your DevOps endeavors!