I'll walk you through dockerizing a Next.js application with different approaches and best practices.
## Basic Docker Setup
### 1. Create a Dockerfile
```dockerfile
# Use official Node.js runtime as base image
FROM node:18-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 --only=production
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 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
ENV PORT=3000
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# Automatically leverage output traces to reduce image size
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
```
### 2. Create .dockerignore file
```dockerignore
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
.gitignore
.env*.local
.vercel
.coverage
.nyc_output
```
### 3. Update next.config.js for standalone output
```javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
// Other configuration options...
}
module.exports = nextConfig
```
## Multi-stage Docker Build (Optimized)
```dockerfile
# Multi-stage build for optimal image size
FROM node:18-alpine AS base
# Stage 1: Dependencies
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
# Stage 2: Builder
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Stage 3: Runner
FROM base AS runner
WORKDIR /app
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# For standalone output
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"]
```
## Development Docker Setup
### Dockerfile for Development
```dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package.json package-lock.json* ./
# Install dependencies
RUN npm ci
# Copy source code
COPY . .
# Expose port
EXPOSE 3000
# Start development server
CMD ["npm", "run", "dev"]
```
### Docker Compose for Development
```yaml
version: '3.8'
services:
nextjs-app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
restart: unless-stopped
```
## Production Docker Compose
```yaml
version: '3.8'
services:
nextjs-app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
# Add other services like database, redis, etc.
# postgres:
# image: postgres:15
# environment:
# POSTGRES_DB: ${DB_NAME}
# POSTGRES_USER: ${DB_USER}
# POSTGRES_PASSWORD: ${DB_PASSWORD}
```
## Build and Run Commands
### Build the Docker image
```bash
# Build production image
docker build -t nextjs-app .
# Build with different tags
docker build -t nextjs-app:latest -t nextjs-app:1.0.0 .
# Build for specific platform
docker build --platform linux/amd64 -t nextjs-app .
```
### Run the container
```bash
# Run in detached mode
docker run -d -p 3000:3000 --name nextjs-container nextjs-app
# Run with environment variables
docker run -d -p 3000:3000 \
-e NODE_ENV=production \
-e DATABASE_URL=your-db-url \
--name nextjs-container nextjs-app
# Run with docker-compose
docker-compose up -d
```
## Advanced Configuration
### 1. Dockerfile with Health Check
```dockerfile
FROM node:18-alpine AS builder
# ... previous stages ...
FROM base AS runner
# ... previous setup ...
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
CMD ["node", "server.js"]
```
### 2. Create healthcheck.js
```javascript
const http = require('http');
const options = {
host: 'localhost',
port: 3000,
path: '/api/health',
timeout: 2000,
};
const request = http.request(options, (res) => {
console.log('STATUS:', res.statusCode);
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
request.on('error', (err) => {
console.log('ERROR', err);
process.exit(1);
});
request.end();
```
### 3. Multi-environment Dockerfile
```dockerfile
ARG NODE_ENV=production
FROM node:18-alpine AS base
# Development stage
FROM base AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
# Production stage
FROM base AS production
# ... production setup ...
```
## Best Practices
### 1. Security Hardening
```dockerfile
FROM node:18-alpine AS runner
# Security best practices
RUN apk add --no-cache dumb-init
RUN chown -R nextjs:nodejs /app
USER nextjs
# Use dumb-init to handle signals properly
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "server.js"]
```
### 2. Optimize Build Cache
```dockerfile
# Copy package files first to leverage Docker cache
COPY package.json package-lock.json* ./
RUN npm ci
# Then copy the rest of the files
COPY . .
```
### 3. Environment-specific Configuration
```dockerfile
# Use build args for environment-specific variables
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
# Set other environment variables
ENV NEXT_TELEMETRY_DISABLED=1
```
## Troubleshooting Common Issues
### 1. Memory Issues during Build
```dockerfile
# Add build arguments for memory limits
ARG NODE_OPTIONS="--max-old-space-size=4096"
ENV NODE_OPTIONS=${NODE_OPTIONS}
```
### 2. Platform-specific Issues
```bash
# Build for specific platform
docker build --platform linux/amd64 -t nextjs-app .
# Use buildx for multi-architecture builds
docker buildx build --platform linux/amd64,linux/arm64 -t nextjs-app .
```
This setup provides a robust foundation for dockerizing your Next.js application with production-ready configurations, security best practices, and optimization techniques.Examples included above
The TSX displays the original content (escaped) and maintains the code fences and blocks. Each code block has inline styling applied via Tailwind + additional inline styles for the container.