Multi-stage build — kichik va xavfsiz image
Muammodan boshlaylik
TypeScript (NestJS) ilova. Yasash uchun kerak: TypeScript kompilyatori, barcha devDependencies, manba kodi. Ishlatish uchun esa — faqat kompilyatsiya qilingan dist/ va production paketlar.
Bitta bosqichli Dockerfile:
FROM node:22
WORKDIR /app
COPY package*.json ./
RUN npm ci # dev paketlar bilan
COPY . .
RUN npm run build
CMD ["node", "dist/main.js"]
Image — 1.4 GB. Ichida TypeScript, eslint, jest, manba kodi, test fayllari — production da hech biri kerak emas. Har bir ortiqcha paket — ko'proq disk, sekinroq deploy va potentsial xavfsizlik zaifligi.
G'oya: yasash va ishlatish — alohida
# ===== 1-bosqich: yasash =====
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ===== 2-bosqich: ishlatish =====
FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/main.js"]
FROM ... AS build— bosqichga nom- Ikkinchi
FROM— yangi, toza image boshlanadi COPY --from=build— birinchi bosqichdan faqat kerakli fayllarni olish- Faqat oxirgi bosqich yakuniy image bo'ladi. Birinchi bosqich (TypeScript, dev paketlar, manba kod) — tashlab yuboriladi
Natija: 1.4 GB → ~180 MB.
Frontend: Node da yasash, Nginx da berish
React / Vite ilova — production da Node umuman kerak emas, faqat statik fayllar:
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build # → /app/dist
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
Yakuniy image — Nginx va bir necha megabayt HTML/JS/CSS. ~50 MB, Node siz. 36-darsda batafsil.
Go: kompilyatsiya qilingan binar
Kompilyatsiya qilinadigan tillarda farq yanada katta:
FROM golang:1.23 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /server .
FROM gcr.io/distroless/static-debian12
COPY --from=build /server /server
USER nonroot
ENTRYPOINT ["/server"]
Go kompilyatori bilan image — ~800 MB. Yakuniy — ~10 MB: faqat bitta binar fayl, shell ham, paket menejeri ham yo'q (17-dars).
Bir nechta bosqich va maqsad (target)
FROM node:22-alpine AS base
WORKDIR /app
COPY package*.json ./
FROM base AS deps
RUN npm ci
FROM deps AS dev
COPY . .
CMD ["npm", "run", "dev"] # ishlab chiqish — hot reload bilan
FROM deps AS build
COPY . .
RUN npm run build
FROM base AS production
ENV NODE_ENV=production
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/main.js"]
Kerakli bosqichni tanlab yasash:
docker build --target dev -t ilova:dev .
docker build --target production -t ilova:1.0 .
docker build -t ilova:1.0 . # target siz — oxirgi bosqich
Bitta Dockerfile — ishlab chiqish va production uchun. Umumiy qismlar (base, deps) bir marta yoziladi.
BuildKit bosqichlarni parallel yasaydi va yakuniy maqsadga kerak bo'lmagan bosqichlarni umuman o'tkazib yuboradi.
Tashqi image dan nusxalash
--from — nafaqat o'z bosqichingizdan, balki istalgan image dan:
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
PHP image ga Composer ni o'rnatish o'rniga — tayyor image dan bitta faylni olish (34-dars).
Multi-stage ning foydalari
| Bir bosqichli | Multi-stage | |
|---|---|---|
| Hajm | Katta (yasash vositalari bilan) | Kichik |
| Xavfsizlik | Kompilyatorlar, dev paketlar — hujum yuzasi | Faqat kerakli |
| Manba kodi image da | Ha | Yo'q (kompilyatsiya qilinadigan tillarda) |
| Deploy tezligi | Sekin (yuklab olish) | Tez |
| Dockerfile soni | Dev va prod uchun alohida | Bitta, --target bilan |
Nima uchun shunday?
Nima uchun yasash vositalarini oxirida RUN rm -rf bilan o'chirib, bitta bosqichda qolish yetmaydi?
14-darsdagi qatlamlar qoidasi: oldingi qatlamda yaratilgan fayl keyingi qatlamda o'chirilsa — u baribir birinchi qatlamda qoladi va image hajmiga kiradi. Faqat bitta ulkan RUN ichida hammasini (o'rnatish, yasash, o'chirish) qilish mumkin — lekin bu keshni butunlay yo'q qiladi va o'qib bo'lmaydigan Dockerfile beradi. Multi-stage bu muammoni tuzilma darajasida hal qiladi: yangi FROM — butunlay toza boshlanish, va siz faqat aniq tanlangan fayllarni o'tkazasiz.
Xulosa
Eslab qoling:
- Multi-stage:
FROM ... AS nom→COPY --from=nom→ faqat oxirgi bosqich qoladi - Yasash vositalari, dev paketlar, manba kod — yakuniy image ga kirmaydi
- Node/TS: build bosqichi +
npm ci --omit=devli production bosqichi - Frontend: Node da build → Nginx da statik fayllar
- Go/Rust: binar → distroless; ~10 MB
--target— bitta Dockerfile dan dev va prodCOPY --from=image— tashqi image dan fayl olish
Keyingi dars
17-dars: Image ni optimallash — alpine, slim, distroless