Next.js Docker ile Deployment Rehberi

Next.js Docker ile Deployment Rehberi
Docker, uygulamalarınızı tutarlı ve tekrarlanabilir ortamlarda çalıştırmanızı sağlayan konteynerizasyon teknolojisidir. Next.js projelerinizi Docker ile deploy etmek, geliştirme ve production ortamları arasındaki farklılıkları ortadan kaldırır. Bu rehberde Next.js uygulamanız için optimize edilmiş Docker image oluşturmayı, multi-stage build kullanmayı ve production'a hazır deployment stratejilerini adım adım inceleyeceğiz.
Neden Docker ile Next.js?
- Tutarlı ortam: Geliştirici makineleri, CI/CD ve production aynı ortamda çalışır
- Kolay ölçeklendirme: Kubernetes, Docker Swarm gibi orchestration araçlarıyla yatay ölçekleme
- İzolasyon: Her uygulama kendi bağımlılıklarıyla izole çalışır
- Tekrarlanabilir build: Aynı Dockerfile her zaman aynı sonucu üretir
- Hızlı deployment: Image bir kez build edilir, her yere deploy edilir
Temel Dockerfile
Basit bir Next.js Dockerfile ile başlayalım:
# Dockerfile
FROM node:20-alpine AS base
WORKDIR /app
# Bağımlılıkları kopyala ve yükle
COPY package.json package-lock.json ./
RUN npm ci
# Uygulama kodunu kopyala
COPY . .
# Build
RUN npm run build
# Production
EXPOSE 3000
ENV NODE_ENV=production
CMD ["npm", "start"]
Multi-Stage Build ile Optimize Edilmiş Dockerfile
Next.js'in resmi olarak önerdiği multi-stage build yaklaşımı, image boyutunu önemli ölçüde küçültür:
# Dockerfile
FROM node:20-alpine AS base
# 1. Bağımlılık aşaması
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
# 2. Build aşaması
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js telemetriyi devre dışı bırak
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# 3. Production aşaması
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Güvenlik: root olmayan kullanıcı oluştur
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Public dosyalarını kopyala
COPY --from=builder /app/public ./public
# Standalone output kopyala
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 Ayarları
Multi-stage build için Next.js'in standalone output modunu etkinleştirin:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
};
module.exports = nextConfig;
output: 'standalone' ayarı, Next.js'in yalnızca production için gerekli dosyaları içeren minimal bir klasör oluşturmasını sağlar. Bu sayede node_modules'un tamamını kopyalamanıza gerek kalmaz.
.dockerignore Dosyası
Gereksiz dosyaların Docker context'ine dahil edilmesini önleyin:
# .dockerignore
node_modules
.next
.git
.gitignore
README.md
docker-compose*.yml
Dockerfile
.env*.local
.vscode
.husky
coverage
__tests__
Docker Compose ile Geliştirme Ortamı
Geliştirme ortamında hot-reload ile çalışmak için Docker Compose kullanabilirsiniz:
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- '3000:3000'
volumes:
- .:/app
- /app/node_modules
- /app/.next
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://postgres:password@db:5432/mydb
depends_on:
- db
db:
image: postgres:16-alpine
ports:
- '5432:5432'
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
# Dockerfile.dev
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
Production Docker Compose
# docker-compose.prod.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
target: runner
ports:
- '3000:3000'
environment:
- DATABASE_URL=${DATABASE_URL}
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
- NEXTAUTH_URL=${NEXTAUTH_URL}
restart: unless-stopped
healthcheck:
test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost:3000/api/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
nginx:
image: nginx:alpine
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- app
restart: unless-stopped
Health Check Endpoint
Docker'ın uygulamanızın sağlığını kontrol edebilmesi için bir API endpoint oluşturun:
// app/api/health/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
try {
// Veritabanı bağlantısı kontrolü eklenebilir
return NextResponse.json(
{
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
},
{ status: 200 }
);
} catch (error) {
return NextResponse.json(
{ status: 'unhealthy', error: String(error) },
{ status: 503 }
);
}
}
CI/CD Pipeline ile Docker Build
GitHub Actions ile otomatik Docker build ve push:
# .github/workflows/docker.yml
name: Docker Build & Push
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
Image Boyutu Optimizasyonu
Docker image boyutunu küçültmek için şu stratejileri uygulayın:
- Alpine base image kullanın:
node:20-alpine(~50MB) vsnode:20(~350MB) - Multi-stage build: Build bağımlılıklarını final image'a dahil etmeyin
- Standalone output: Next.js'in minimal output modunu kullanın
- .dockerignore: Gereksiz dosyaları build context'inden çıkarın
- Layer caching: Sık değişen dosyaları Dockerfile'ın sonuna koyun
docker images komutuyla image boyutlarını karşılaştırın. İyi optimize edilmiş bir Next.js standalone image genellikle 150-200MB civarında olmalıdır.
Sonuç
Docker ile Next.js deployment, uygulamanızı tutarlı, güvenli ve ölçeklenebilir şekilde çalıştırmanın en etkili yollarından biridir. Multi-stage build ile image boyutunu minimize edin, standalone output modunu etkinleştirin ve non-root kullanıcıyla çalıştırarak güvenliği artırın. Docker Compose ile hem geliştirme hem de production ortamlarınızı kolayca yönetebilirsiniz.