Docker — Next.js ni containerlashtirish
Muammodan boshlaylik
Vercel qulay, lekin:
- Kompaniya o'z serverlarida ishlashni talab qiladi (ma'lumotlar mamlakat ichida)
- Trafik katta — Vercel hisobi qimmatlashdi
- Ilova boshqa xizmatlar (baza, Redis, worker) bilan birga Kubernetes da ishlashi kerak
Serverga to'g'ridan-to'g'ri npm install && npm run build — "mening kompyuterimda ishlaydi" muammolari: boshqa Node.js versiyasi, boshqa OS kutubxonalari.
Docker — ilovani muhiti bilan birga qadoqlash: hamma joyda bir xil ishlaydi.
Hayotiy o'xshatma
Tayyor ovqat konteyneri. Restoran taomni maxsus idishda muhrlab beradi — uni qayerga olib borsangiz ham, ichidagi narsa bir xil. Qabul qiluvchi oshxona jihozlariga (serverga) bog'liq emas — faqat isitib (ishga tushirib) yeydi.
standalone rejim
Odatiy next build natijasi — node_modules bilan birga yuzlab MB. Standalone rejimda Next.js faqat kerakli fayllarni alohida papkaga yig'adi:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
output: 'standalone',
}
export default nextConfig
.next/standalone/
├── server.js ← ishga tushirish fayli (next start shart emas)
├── node_modules/ ← faqat kerakli paketlar
└── .next/
Image hajmi — ~1 GB o'rniga ~150–200 MB.
Dockerfile
# 1. Bog'liqliklar
FROM node:22-alpine AS deps
WORKDIR /app
RUN apk add --no-cache libc6-compat
COPY package.json package-lock.json ./
RUN npm ci
# 2. Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npx prisma generate
RUN npm run build
# 3. Ishga tushirish
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
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"]
| Bosqich | Nima |
|---|---|
deps |
npm ci — kesh: package.json o'zgarmasa qayta bajarilmaydi |
builder |
next build |
runner |
Faqat standalone natija — kichik va xavfsiz image |
[!WARNING]
public/va.next/staticstandalone papkaga avtomatik nusxalanmaydi — ularni alohidaCOPYqiling. Aks holda sahifa ochiladi, lekin CSS, JS va rasmlar 404 bo'ladi.
.dockerignore
node_modules
.next
.git
.env*
!.env.example
npm-debug.log
e2e
coverage
.env fayllarini image ga qo'shmang — maxfiy kalitlar image ichida qoladi va image ni olgan har kim ularni o'qiydi.
Build va run
docker build -t dokon-web .
docker run -d --name dokon-web -p 3000:3000 \
--env-file .env.production \
--restart unless-stopped \
dokon-web
NEXT_PUBLIC_ muammosi
NEXT_PUBLIC_ o'zgaruvchilar build paytida yoziladi (65-dars). docker run --env-file da berilgani ularga ta'sir qilmaydi.
# builder bosqichida
ARG NEXT_PUBLIC_SITE_URL
ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL
RUN npm run build
docker build --build-arg NEXT_PUBLIC_SITE_URL=https://dokon.uz -t dokon-web .
Bitta image ni ko'p muhitda ishlatish kerak bo'lsa — ochiq qiymatlarni ham server o'zgaruvchisi sifatida o'qib, client ga uzating (65-dars).
Docker Compose — baza bilan
# compose.yaml
services:
web:
build:
context: .
args:
NEXT_PUBLIC_SITE_URL: https://dokon.uz
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://dokon:${DB_PAROL}@db:5432/dokon
AUTH_SECRET: ${AUTH_SECRET}
AUTH_TRUST_HOST: "true"
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:17-alpine
environment:
POSTGRES_USER: dokon
POSTGRES_PASSWORD: ${DB_PAROL}
POSTGRES_DB: dokon
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dokon"]
interval: 5s
retries: 10
restart: unless-stopped
volumes:
pgdata:
docker compose up -d --build
docker compose exec web npx prisma migrate deploy
[!INFO] Standalone image da
prismaCLI bo'lmasligi mumkin (udevDependenciesda). Migratsiyalarni alohida bosqichda (CI, alohida "migrate" container) yoki CLI nidependenciesga o'tkazib bajaring.
Self-hosted da e'tibor berish kerak
| Mavzu | Tafsilot |
|---|---|
| ISR va kesh | Kesh container ichida, diskda. Bir nechta nusxa bo'lsa — har birining o'z keshi; umumiy kesh uchun cacheHandler (Redis) |
| Rasm optimizatsiyasi | sharp — CPU talab qiladi; katta trafikda CDN |
| Health check | /api/health Route Handler — orkestrator uchun |
| Signallar | CMD ["node", "server.js"] — SIGTERM to'g'ri uzatiladi (npm start emas) |
| Proxy ortida | Nginx (68-dars), AUTH_TRUST_HOST=true |
[!TIP] Rasmiy Next.js repozitoriyasidagi
examples/with-docker— har bir yangi versiya uchun yangilanib turadigan tavsiya etilgan Dockerfile. Uni boshlang'ich nuqta sifatida oling.
Tez-tez uchraydigan xatolar
1. Statik fayllar 404
public va .next/static nusxalanmagan.
2. Container tashqaridan ochilmaydi
HOSTNAME=0.0.0.0 yo'q — server faqat container ichidagi localhost da tinglaydi.
3. NEXT_PUBLIC_ qiymati undefined
docker run -e bilan berilgan — kech; build ARG orqali.
Xulosa
output: 'standalone' — faqat kerakli fayllar, kichik image
Multi-stage: deps → builder → runner; root emas (USER nextjs)
public va .next/static — alohida COPY
CMD ["node", "server.js"]; HOSTNAME=0.0.0.0
.dockerignore: node_modules, .next, .env*
NEXT_PUBLIC_ — build ARG; maxfiy — runtime --env-file
Compose — baza bilan; migratsiya — alohida qadam
Self-hosted: kesh, sharp, health check, proxy
Keyingi dars
68-dars: Self-hosted — VPS da deploy, Nginx sozlash
O'z serveringizda Next.js — PM2 yoki Docker, Nginx va SSL bilan.