Dockerizing Next.js
Containerize your Next.js application with Docker
🐳 What is Docker?
Docker packages your Next.js app with all dependencies into a container that runs consistently anywhere. It ensures your app works the same in development, testing, and production environments, eliminating "works on my machine" problems.
# Build Docker image
docker build -t my-nextjs-app .
# Run container
docker run -p 3000:3000 my-nextjs-app
Docker Benefits
Consistency
Same environment everywhere
Portability
Run anywhere Docker runs
Scalability
Easy to scale horizontally
Isolation
Apps run in isolated containers
🔹 Basic Dockerfile
Create a Dockerfile to containerize your Next.js app. This multi-stage build optimizes image size by separating dependencies installation from the final runtime. It uses Node.js Alpine for a smaller footprint and faster deployments.
# Dockerfile
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
# Build the app
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Production image
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]
🔹 Configure Next.js for Docker
Enable standalone output mode in Next.js configuration. This creates a minimal production build with only necessary files, reducing Docker image size significantly. The standalone mode includes a built-in server for running your app.
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
// Optional: Reduce image size further
experimental: {
outputFileTracingRoot: undefined,
},
}
module.exports = nextConfig
🔹 Create .dockerignore
Exclude unnecessary files from Docker build context. This speeds up builds and reduces image size by preventing node_modules, git files, and other development artifacts from being copied into the container.
# .dockerignore
node_modules
.next
.git
.gitignore
README.md
.env*.local
.vscode
.idea
npm-debug.log
yarn-error.log
.DS_Store
🔹 Build and Run Docker Image
Build your Docker image and run it locally. The build process installs dependencies, compiles your Next.js app, and packages everything into a container. You can then run multiple instances or deploy to any Docker-compatible platform.
# Build the Docker image
docker build -t my-nextjs-app .
# Run the container
docker run -p 3000:3000 my-nextjs-app
# Run with environment variables
docker run -p 3000:3000 \
-e DATABASE_URL="your-db-url" \
-e API_KEY="your-api-key" \
my-nextjs-app
# Run in detached mode (background)
docker run -d -p 3000:3000 --name nextjs-container my-nextjs-app
# View running containers
docker ps
# Stop container
docker stop nextjs-container
🔹 Docker Compose Setup
Use Docker Compose to manage multi-container applications. This is useful when your Next.js app needs a database, Redis, or other services. Docker Compose orchestrates all services with a single command.
# docker-compose.yml
version: '3.8'
services:
nextjs:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- NODE_ENV=production
depends_on:
- db
restart: unless-stopped
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop all services
docker-compose down
🔹 Optimize Docker Image
Reduce image size and improve build times with optimization techniques. Use multi-stage builds, Alpine Linux base images, and layer caching. Smaller images deploy faster and use less storage.
Optimization Tips:
- Multi-stage builds: Separate build and runtime stages
- Alpine images: Use lightweight Alpine Linux base
- Layer caching: Order commands to maximize cache hits
- .dockerignore: Exclude unnecessary files
- Standalone output: Use Next.js standalone mode
# Check image size
docker images my-nextjs-app
# Remove unused images
docker image prune -a
# Build with no cache (fresh build)
docker build --no-cache -t my-nextjs-app .