10.4-bob: Docker Compose va multi-stage build
10-QISM — DevOps va Deploy · 4-mavzu
1. Kirish va motivatsiya
10.3da bitta ilovani Docker image'ga qadoqlab, docker run bilan ishga tushirdik. Lekin real loyiha hech qachon bitta konteyner emas. Oddiy backend ilovasini eslang: NestJS ilovasi 10.3-bob ishlaydi, lekin u PostgreSQL 6.6-bob ga ulanadi, sessiya va cache uchun Redis 5.21-bob kerak, oldida esa so'rovlarni qabul qiladigan Nginx 10.2-bob turadi. Demak — kamida to'rtta konteyner, va ular bir-biri bilan gaplashishi kerak.
Endi tasavvur qil: bularning har birini qo'lda ko'tarish. Avval tarmoq yaratasiz (docker network create), keyin Postgres'ni uzun flaglar bilan ishga tushirasiz (-e POSTGRES_PASSWORD, -v pgdata:..., --network, --name), keyin Redis'ni, keyin ilovani (yana -e DATABASE_URL, -e REDIS_URL, --network, -p), keyin Nginx'ni. Bu — uzun, yodda saqlash qiyin, xatoga moyil jarayon. Har safar serverni qayta ko'targanda yana o'sha 5-6 ta uzun buyruqni to'g'ri tartibda yozishing kerak. Junior dasturchi shu yerda chalkashadi; senior esa butun tizimni bitta faylga yozib, bitta buyruq bilan ko'taradi — bu Docker Compose.
Docker Compose — ko'p konteynerli ilovani bitta compose.yaml faylda ta'riflaydigan va boshqaradigan vosita. Faylda barcha service (servis — ilovani tashkil etuvchi har bir konteyner: app, db, redis, nginx), ularning tarmog'i (network) va doimiy ma'lumoti (volume) bir joyda yoziladi. Keyin docker compose up — va butun tizim bir buyruqda, to'g'ri tartibda ko'tariladi. docker compose down — hammasini tozalaydi. Bu bobning ikkinchi yarmi — multi-stage build (ko'p bosqichli qurish): image'ni ikki qismga ajratib (build bosqichi + ishlash bosqichi), production image hajmini bir necha barobar kichraytirish texnikasi.
O'xshatish: Docker Compose — orkestr dirijyori. Orkestrda ko'p cholg'u bor: skripka (app), violonchel (DB), nay (Redis), baraban (Nginx) — har biri alohida, lekin ular birga, muvofiqlashtirilgan holda chalishi kerak. Har bir musiqachiga alohida "boshla", "to'xta" deb baqirsangiz — tartibsizlik bo'ladi. Dirijyor esa bitta tayoq harakati bilan hammasini boshqaradi: kim qachon kiradi (
depends_on— DB avval tayyor bo'lsin), kim kim bilan gaplashadi (tarmoq), qaysi nota chalinadi (sozlamalar).compose.yaml— partitura (nota varag'i): butun "asar" qanday ijro etilishi yozilgan.docker compose up— dirijyor tayog'ini ko'tarishi: hamma cholg'u bir vaqtda, to'g'ri tartibda boshlaydi. Siz endi har bir musiqachi bilan emas, butun orkestr bilan bitta partitura orqali ishlaysiz.
Nega muhim?
- Bir buyruq — butun stack —
docker compose upapp+DB+Redis+Nginx'ni birga ko'taradi (qo'lda 5-6 buyruq o'rniga). - Takrorlanadigan muhit —
compose.yamlGit'da; har kim bir xil tizimni bir xil ko'taradi (lokal = jamoa = CI). - Multi-stage = kichik image — build vositalari production'da qolmaydi; image hajmi keskin kichrayadi (tez deploy, kam xavf).
- Intervyu/ish — 2026da har backend e'lonida "Docker Compose" talab qilinadi (lokal dev va kichik deploy standarti).
2. Nazariya — chuqur tushuntirish
2.1. Compose nima va qaysi muammoni hal qiladi
MUAMMO: real ilova = KO'P konteyner (qo'lda boshqarish og'ir):
$ docker network create mynet
$ docker run -d --name db --network mynet \
-e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data postgres:17
$ docker run -d --name redis --network mynet redis:7-alpine
$ docker run -d --name app --network mynet -p 3000:3000 \
-e DATABASE_URL=... -e REDIS_URL=... myapp:1.0
$ docker run -d --name nginx --network mynet -p 80:80 -v ...:/etc/nginx nginx
uzun, tartib muhim, yodda saqlash qiyin, har safar qayta yozish
YECHIM: COMPOSE — hammasini BITTA faylga (compose.yaml) yoz:
$ docker compose up -d butun tizim BIR buyruqda ko'tariladi
$ docker compose down hammasini to'xtatib, tozalaydi
deklarativ (NIMA kerakligini yozasan, QANDAY emas)
Git'da saqlanadi (takrorlanadigan)
tarmoq/tartib avtomatikDocker Compose — ko'p konteynerli ilovani bitta YAML faylda ta'riflab, bir buyruq bilan boshqaradigan vosita. Muammo aniq: real ilova bir nechta konteynerdan iborat (10.3: 2.8 — networking), va ularni qo'lda
docker runbilan ko'tarish — uzun, tartibga bog'liq, takrorlash qiyin. Compose deklarativ: siz nima kerakligini yozasiz (qaysi servislar, qanday sozlamalar, qanday bog'lanish), Docker esa qanday qilishni o'zi hal qiladi. Butun tizimcompose.yamlfaylida — uni Git'ga qo'shasiz, va har kim (siz, jamoadosh, CI server) aynan bir xil tizimni ko'taradi. Tarmoq, ishga tushirish tartibi, ma'lumot saqlash — hammasi bitta faylda. Compose ayniqsa lokal development va kichik/o'rta production uchun ideal (katta miqyos uchun — Kubernetes, 10.8).
2.2. compose.yaml anatomiyasi (services, networks, volumes)
COMPOSE.YAML — uchta asosiy yuqori darajadagi (top-level) blok:
services: ASOSIY: har bir konteyner (app, db, redis...)
app: servis nomi (= tarmoqda hostname — 2.4)
build: . yoki image: myapp:1.0
ports: ["3000:3000"]
db:
image: postgres:17
volumes: [pgdata:/var/lib/postgresql/data]
networks: (ixtiyoriy) maxsus tarmoqlar
backend: Compose avtomatik default ham yaratadi 2.4-bob
volumes: named volume'lar (DB ma'lumoti — 2.5)
pgdata: Docker boshqaradigan doimiy saqlash
FAYL NOMI: compose.yaml (zamonaviy) yoki docker-compose.yml (eski, hali ishlaydi)
"version:" — ESKIRGAN (obsolete) — endi YOZMA (2026)
compose.yamlanatomiyasi — uchta asosiy yuqori darajadagi blokdan iborat:services(eng muhimi — har bir konteyner shu yerda: app, db, redis, nginx; har birining nomi bor),networks(ixtiyoriy — maxsus tarmoqlar, lekin Compose default tarmoqni avtomatik yaratadi — 2.4),volumes(named volume'lar — DB ma'lumoti uchun, 2.5). Fayl nomi: zamonaviy standart —compose.yaml(compose-spec rasmiy nomi), lekin eskidocker-compose.ymlham hali ishlaydi (orqaga moslik). Eng muhim 2026 o'zgarish: yuqoridagi eskiversion: "3.8"qatori endi eskirgan (obsolete) — uni umuman yozmang, Compose o'zi eng yangi spetsifikatsiyani ishlatadi (yozsangiz ogohlantirish chiqaradi). YAML — bo'shliqqa sezgir (indentatsiya muhim, tab emas, probel).
2.3. Service ta'rifi (image vs build, ports, environment, env_file)
HAR SERVIS — bir konteynerni ta'riflaydi (asosiy atributlar):
services:
app:
build: . Dockerfile'dan QUR (o'z kodimiz)
# YOKI: image: myapp:1.0 tayyor image (registry'dan)
ports:
- "3000:3000" XOST:KONTEYNER (10.3: 2.8)
environment: muhit o'zgaruvchilari (inline)
- NODE_ENV=production
- DATABASE_URL=postgres://db:5432/app
env_file: yoki fayldan (ko'p o'zgaruvchi — 2.7)
- .env
restart: unless-stopped yiqilsa qayta yoq (10.1: 2.6)
build (o'z ilovamiz) vs image (tayyor: postgres, redis, nginx)
environment USTUN turadi env_file ustidan (override)Service ta'rifi — har bir servis bitta konteynerni ta'riflaydi. Asosiy atributlar:
image— tayyor image (postgres:17,redis:7,nginx— registry'dan olinadi) yokibuild— Dockerfile'dan qurish (o'z ilovamiz uchun:build: .— joriy papkadagi Dockerfile). Qoida: boshqalarning servisi (DB, Redis, Nginx)image; o'z ilovangbuild.ports— port mapping ("3000:3000"— XOST:KONTEYNER, 10.3: 2.8).environment— muhit o'zgaruvchilari to'g'ridan-to'g'ri (inline).env_file— o'zgaruvchilarni fayldan o'qish (.env— ko'p o'zgaruvchi uchun qulay, 2.7).restart— qayta ishga tushirish siyosati (unless-stopped,always,on-failure— 10.1: 2.6 systemd'dagi g'oya). Ustunlik:environmentqiymatienv_filedagini ustidan yozadi (override). YAML ro'yxat (-) yoki map (KEY: value) shaklida yozish mumkin.
2.4. Tarmoq — Compose avtomatik network va DNS
COMPOSE — barcha servislarga BITTA default tarmoq yaratadi (avtomatik):
┌─────────────────────────────────────────────────┐
│ DEFAULT NETWORK (loyiha nomi + "_default") │
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ app │───►│ db │ │ redis │ │
│ └────────┘ └────────┘ └────────┘ │
│ │
│ SERVIS NOMI = HOSTNAME (Docker ichki DNS): │
│ app db'ga: host=db, port=5432 (IP KERAK EMAS)│
│ app redis'ga: host=redis, port=6379 │
└─────────────────────────────────────────────────┘
DATABASE_URL=postgres://user:pass@db:5432/mydb
└─ servis NOMI (db), localhost EMAS!
Maxsus tarmoq (networks:) — servislarni AJRATISH uchun (2.10)Tarmoq — Compose'ning eng kuchli qulayligi. Compose avtomatik ravishda barcha servislar uchun bitta default tarmoq yaratadi (nomi: loyiha +
_default). Eng muhim natija: servis nomi = hostname. Docker ichki DNS orqali har bir servis boshqasini nomi bilan topadi — IP manzil kerak emas (10.3: 2.8 — qo'ldadocker network createqilgan ishni Compose o'zi bajaradi). Masalanappservisidbservisiga ulanmoqchi bo'lsa, ulanish manzili:postgres://db:5432— bu yerdadb— servis nomi (localhostemas! chunki DB boshqa konteynerda,localhosto'sha konteynerning o'zini bildiradi). Redis uchun:redis://redis:6379. Eng keng tarqalgan xato —localhostga ulanish (Xato 5). Maxsus tarmoqlar (networks:bloki) servislarni bir-biridan ajratish uchun ishlatiladi (masalan DB faqat backend tarmoqda — 2.10).
2.5. Volume — named volume (DB ma'lumoti)
MUAMMO: konteyner o'chsa — ichidagi ma'lumot YO'QOLADI (10.3: 2.7)
"docker compose down" qilsang — DB ma'lumoti ham ketadimi?
YECHIM: NAMED VOLUME — Docker boshqaradigan doimiy saqlash:
services:
db:
image: postgres:17-alpine
volumes:
- pgdata:/var/lib/postgresql/data named volume DB papkasi
# └─ konteyner ICHIDA DB shu yerda
volumes: top-level: named volume'ni e'lon qil
pgdata: Docker o'zi joylashtiradi (/var/lib/docker/volumes)
"docker compose down" konteyner o'chadi, VOLUME QOLADI
"docker compose down -v" volume ham O'CHADI (ehtiyot bo'l — DB ketadi!)Volume — DB ma'lumotini saqlash uchun majburiy. Muammo (10.3: 2.7): konteyner o'chsa, ichiga yozilgan ma'lumot yo'qoladi —
docker compose downqilganda DB ma'lumoti ham ketib qolmasin. Yechim — named volume: servis ichidavolumes: - pgdata:/var/lib/postgresql/data(volume nomi konteyner ichidagi DB papkasi), va top-levelvolumes:blokidapgdatani e'lon qilasiz. Docker volume'ni o'zi joylashtiradi (/var/lib/docker/volumes) va konteyner o'chsa ham saqlab qoladi. Juda muhim farq:docker compose down— konteynerlarni o'chiradi, lekin volume qoladi (DB ma'lumoti saqlanadi — qaytaupqilganda joyida).docker compose down -v— volume'larni ham o'chiradi (DB ma'lumoti butunlay ketadi — ehtiyot bo'l, faqat toza boshlash kerak bo'lganda ishlat). Bind mount (xost papkasi) — dev/config uchun, named volume — DB uchun (10.3: 2.7).
2.6. depends_on va ishga tushish tartibi (healthcheck nega kerak)
MUAMMO: app DB'dan oldin ko'tarilsa ulanolmaydi (DB hali tayyor emas):
depends_on:
- db FAQAT TARTIB: db AVVAL ishga tushadi
# LEKIN "ishga tushdi" ≠ "TAYYOR" (qabul qilishga)!
# Postgres jarayoni boshlandi, lekin hali init qilyapti
DB jarayoni boshlanishi bilan ulanishni qabul qilmaydi (bir necha sekund init)
app darrov ulanmoqchi "connection refused" app yiqiladi
YECHIM: HEALTHCHECK + condition (DB HAQIQATAN tayyorligini kut):
services:
db:
image: postgres:17-alpine
healthcheck: DB sog'ligini tekshir (10.3: 2.5)
test: ["CMD-SHELL", "pg_isready -U app"] qabul qilishga tayyormi?
interval: 5s
timeout: 3s
retries: 5
app:
depends_on:
db:
condition: service_healthy db HEALTHY bo'lguncha KUT, keyin app
depends_onva ishga tushish tartibi — eng ko'p adashtiradigan mavzu. Oddiydepends_on: - dbfaqat tartibni belgilaydi:dbappdan avval ishga tushadi. Lekin "ishga tushdi" (started) ≠ "tayyor" (ready): PostgreSQL konteyneri ko'tariladi, jarayon boshlanadi, lekin u bir necha sekund initsializatsiya qiladi (ma'lumotlar bazasini sozlash) va shu paytda ulanishni qabul qilmaydi. Agarappdarrov ulanmoqchi bo'lsa —connection refusedxatosi ilova yiqiladi. Yechim — healthcheck + condition: DB servisigahealthcheckqo'yasiz (pg_isready— Postgres ulanishga tayyormi tekshiradigan buyruq, 10.3: 2.5), vaappdadepends_onni uzun shaklda yozasiz:condition: service_healthy— buappni DB healthy bo'lgunicha kuttiradi. Condition turlari:service_started(faqat ishga tushdi — default),service_healthy(healthcheck o'tdi — DB uchun shu kerak),service_completed_successfully(servis ishini tugatib chiqdi — masalan migratsiya/seed). Production'da DB'ga bog'liq servis doimservice_healthyishlatishi kerak.
2.7. env va .env fayl (interpolatsiya)
IKKI XIL ".env" ROLI — chalkashtirma:
1) HOST .env — Compose O'ZI o'qiydi (compose.yaml ichida ${...} bilan):
# .env (compose.yaml yonida)
POSTGRES_PASSWORD=secret
APP_PORT=3000
# compose.yaml — ${...} bilan interpolatsiya:
services:
db:
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} .env'dan o'qiladi
app:
ports: ["${APP_PORT}:3000"] .env'dan
2) SERVIS env_file — KONTEYNER ichiga uzatiladi (ilova o'qiydi):
services:
app:
env_file: [.env] .env'dagi HAMMA o'zgaruvchi konteynerga
${VAR} compose.yaml'ni to'ldiradi ; env_file konteynerga beradi
.env hech qachon Git'ga TUSHMASIN (.gitignore) — maxfiy (10.11)
.envva interpolatsiya — ikki xil rol bor, ko'pchilik chalkashtiradi. (1) Host.env— Compose o'zi o'qiydi:compose.yamlichida${VAR}yozsangiz, Compose o'sha qiymatnicompose.yamlyonidagi.envfaylidan oladi (interpolatsiya — matnni qiymat bilan to'ldirish). Bu yashirin sozlamalarni (parol, port) faylga olib chiqib,compose.yamlni umumiy qilishga imkon beradi. (2) Servisenv_file— fayldagi o'zgaruvchilarni konteyner ichiga uzatadi (ilovaning o'ziprocess.envdan o'qiydi — 5.8). Farqni yodda tuting:${VAR}—compose.yamlmatnini to'ldiradi (Compose darajasi);env_file— konteynerga o'zgaruvchi beradi (ilova darajasi). Compose default'da.envfaylni avtomatik o'qiydi (${...}uchun). Xavfsizlik:.env(maxfiy parollar) hech qachon Git'ga tushmasin —.gitignorega qo'shing, o'rniga.env.example(bo'sh shablon) qo'ying (10.11 — secrets boshqaruvi).
2.8. profiles (servislarni shartli yoqish)
PROFILES — ba'zi servislarni FAQAT kerak bo'lganda yoqish:
services:
app:
build: . har doim ishlaydi (profil yo'q)
db:
image: postgres:17 har doim
pgadmin:
image: dpage/pgadmin4
profiles: [debug] FAQAT "debug" profil yoqilsa ishlaydi
seeder:
build: .
command: npm run seed
profiles: [tools] FAQAT "tools" yoqilsa
ISHLATISH:
docker compose up app + db (profilsizlar)
docker compose --profile debug up + pgadmin
COMPOSE_PROFILES=debug,tools docker compose up bir nechta profil
Profilsiz servis — DOIM ishlaydi; profilli — faqat yoqilganda
profiles— ba'zi servislarni faqat kerak bo'lganda yoqish mexanizmi. Servisgaprofiles: [debug]qo'ysangiz — u faqatdebugprofil yoqilganda ishga tushadi; oddiydocker compose upda e'tiborga olinmaydi. Qoida: profilsiz servis doim ishlaydi (app, db); profilli servis faqat profil aktivlashtirilganda. Yoqish:docker compose --profile debug upyokiCOMPOSE_PROFILES=debug docker compose up(bir nechta — vergul bilan:debug,tools). Bu nimaga foydali? Bir xilcompose.yamlda: asosiy servislar (app, db) + faqat developmentda kerak bo'ladigan qo'shimchalar — pgAdmin (DB ko'rish), seeder (test ma'lumot to'ldirish), debug vositalari. Production'da ularni ko'tarmaysiz, dev'da--profilebilan yoqasiz. Bu — bitta fayl bilan turli muhitlarni boshqarishning toza usuli (override bilan birga — 2.9).
2.9. override va bir nechta compose fayl (dev/prod)
MUAMMO: dev va prod sozlamalari har xil (port, build vs image, volume):
ikkita to'liq fayl saqlash — takror, sinxronlash qiyin
YECHIM: BAZA + OVERRIDE (qatlamlab birlashtirish — merge):
compose.yaml BAZA (umumiy: servislar, tarmoq)
compose.override.yaml DEV qo'shimcha (avtomatik qo'shiladi)
compose.prod.yaml PROD qo'shimcha (qo'lda ko'rsatiladi)
# compose.override.yaml (DEV — bind mount, hot-reload):
services:
app:
build:
target: dev multi-stage'dagi dev bosqich 2.11-bob
volumes:
- ./src:/app/src kod o'zgarishi darrov ko'rinsin (10.3: 2.7)
command: npm run dev
ISHLATISH:
docker compose up baza + override (DEV auto)
docker compose -f compose.yaml -f compose.prod.yaml up baza + PRODOverride va bir nechta fayl — dev va prod sozlamalarini boshqarishning toza usuli. Muammo: development (bind mount, hot-reload, debug portlar) va production (optimal image, restart siyosati) sozlamalari har xil; ikkita to'liq nusxa saqlash — takror va sinxronlash qiyin. Yechim — baza + override (qatlamlab birlashtirish, merge):
compose.yaml(umumiy — servislar, tarmoq, volume) +compose.override.yaml(dev qo'shimchalari — Compose buni avtomatik qo'shadi) +compose.prod.yaml(prod — qo'lda ko'rsatiladi). Sehr:docker compose updeganingda Composecompose.yaml+compose.override.yamlni birlashtiradi (override baza ustiga "yopishtiriladi"). Production uchun esa override'ni o'tkazib,-f compose.yaml -f compose.prod.yamlbilan boshqa qatlamni qo'shasiz. Bu — DRY (takror yo'q): umumiy qism bir joyda, faqat farqlar override'da.-fbilan ko'rsatilgan fayllar tartib bo'yicha birlashadi (keyingisi oldingini ustidan yozadi).
2.10. networks bilan ajratish va scale
TARMOQ AJRATISH — xavfsizlik (DB tashqi tarmoqdan ko'rinmasin):
services:
nginx:
networks: [frontend] faqat frontend tarmoqda
app:
networks: [frontend, backend] IKKALA tarmoqda (ko'prik)
db:
networks: [backend] faqat backend (nginx ko'rmaydi!)
networks:
frontend:
backend:
nginx db'ga to'g'ridan ulanolmaydi (alohida tarmoq) — XAVFSIZ
app ikkala tarmoqda — o'rtada (10.1: 2.7 — least exposure)
SCALE — bir servisning bir necha nusxasi (gorizontal):
docker compose up --scale app=3 app'ning 3 nusxasi (Nginx oldida balanslar)
scale uchun servisda qat'iy "ports" bo'lmasligi kerak (konflikt)Tarmoq ajratish va scale — ikki ilg'or imkoniyat. Tarmoq ajratish (xavfsizlik): har bir servisni alohida tarmoqqa qo'yib, kim kim bilan gaplasha olishini cheklaysiz. Masalan
nginx—frontendtarmoqda,db—backendtarmoqda,app— ikkalasida (ko'prik). Natijadanginxto'g'ridan-to'g'ridbga ulanolmaydi (alohida tarmoqlar) — bu xavfsizlik: agar Nginx buzilsa, DB undan himoyalangan (10.1: 2.7 — eng kam ochiqlik, faqat keraklisi ulansin). Scale — bir servisning bir necha nusxasini ko'tarish (gorizontal masshtablash — 9.9):docker compose up --scale app=3—appning 3 nusxasi ishlaydi, Nginx (10.2 — load balancer) oldida yukni taqsimlaydi. Scale uchun servisda qat'iyportsbo'lmasligi kerak (3 nusxa bir xost portini band qila olmaydi — konflikt). Bu — Compose'ning chegarasi; haqiqiy auto-scaling/orkestratsiya uchun Kubernetes 10.8-bob.
2.11. MULTI-STAGE BUILD (build vs runtime bosqich)
MUAMMO: build vositalari final image'da QOLADI (katta, xavfli):
BITTA STAGE (10.3: Misol 10) — hammasi bitta image'da:
- TypeScript kompilyator, @nestjs/cli, devDependencies, manba kod
- npm run build dist/ ; LEKIN build vositalari ham QOLADI ~400 MB
MULTI-STAGE — IKKI bosqich, oxirgisiga FAQAT natija ko'chiriladi:
# ── 1-BOSQICH: BUILDER (quradi — vositalar shu yerda) ──
FROM node:22-alpine AS builder "builder" deb NOMLAYMIZ
WORKDIR /app
COPY package*.json ./
RUN npm ci HAMMA qaramlik (dev ham — build uchun)
COPY . .
RUN npm run build dist/ hosil bo'ladi
# ── 2-BOSQICH: RUNTIME (faqat ishlatadi — toza, kichik) ──
FROM node:22-alpine YANGI, toza image
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev FAQAT production qaramlik
COPY --from=builder /app/dist ./dist faqat NATIJA (builder'dan)
USER node
CMD ["node", "dist/main.js"]
~150 MB (build vositalari YO'Q — final image'da kerak emas)Multi-stage build — bu bobning eng kuchli texnikasi (10.3: 2.10da ishora qilingan). Muammo: bitta bosqichli Dockerfile'da (10.3: Misol 10) build vositalari final image'da qoladi — TypeScript kompilyator,
@nestjs/cli, barcha devDependencies, manba kod. Ular faqat build paytida kerak (npm run build), lekin ishlayotgan konteynerga kerak emas (faqat tayyordist/kerak). Natijada image400 MB — katta va xavfli (ko'p keraksiz fayl = katta attack surface). Yechim — multi-stage: bir nechta400 MBFROMishlatib, image'ni bosqichlarga ajratasiz. Mexanizm: (1) builder bosqichi —FROM ... AS builderdeb nomlaysiz, unda hamma qaramlikni o'rnatib (npm ci— dev ham), kodni build qilasiz (dist/hosil bo'ladi). (2) runtime bosqichi — yangi, tozaFROMbilan boshlanadi, faqat production qaramlik (npm ci --omit=dev) va eng muhimiCOPY --from=builder /app/dist ./dist— builder bosqichidan faqat natijani ko'chiradi. Final image'ga faqat oxirgi bosqich kiradi — build vositalari butunlay tashlanadi. Natija: image hajmi bir necha barobar kichrayadi (150 MB). Yana:10 MB).--target=builderbilan faqat ma'lum bosqichgacha qurish mumkin (dev/debug/test uchun — 2.9, Misol 6b) — bosqichlardeps build test productionshaklida bo'linsa, CI test bosqichigacha, deploy esa production bosqichigacha quradi 10.5-bob. Build tezligini oshirish uchun cache mount ishlatiladi:RUN --mount=type=cache,target=/root/.npm npm ci— bunda paket menejerining cache'i build'lar orasida saqlanadi, shu sabab keyingi build'da qaramliklar qayta yuklanmaydi (Misol 6b). Go/Rust uchun multi-stage yanada keskin:FROM scratch(bo'sh baza) ga faqat kompilyatsiya qilingan binar fayl ko'chiriladi (
2.12. Compose vs Kubernetes (qisqacha)
COMPOSE vs KUBERNETES — qachon qaysi biri:
DOCKER COMPOSE: KUBERNETES (K8s):
- 1 mashina (xost) - KO'P mashina (klaster)
- oddiy, bitta YAML - murakkab (ko'p obyekt: Pod, Service...)
- lokal dev + kichik prod - katta production, miqyos
- qo'lda scale (--scale) - AVTO-scale, self-healing, rolling update
- bitta server yiqilsa — hammasi - bir nuqta yiqilsa — qayta joylashtiradi
Compose — boshlang'ich va o'rta loyiha uchun YETARLI (90% holat)
Katta miqyos kerak bo'lganda — Kubernetes (TO'LIQ 10.8da)Compose vs Kubernetes — ikkalasi ham konteyner orkestratsiyasi, lekin miqyosi har xil. Docker Compose — bitta mashinada (xost) ishlaydi, oddiy (bitta YAML), lokal development va kichik/o'rta production uchun ideal; scale qo'lda (
--scale). Kubernetes (K8s) — ko'p mashinali klaster: murakkab (ko'p obyekt turi — Pod, Service, Deployment), lekin avto-scaling, self-healing (yiqilgan konteynerni avtomatik qayta ko'taradi), rolling update (uzilishsiz yangilash) beradi — katta production uchun. Muhim xulosa: boshlanish uchun Compose yetarli (holatlarning ~90%i — kichik/o'rta loyiha bitta serverda); Kubernetes faqat haqiqiy katta miqyos (yuzlab konteyner, ko'p server, yuqori mavjudlik) kerak bo'lganda. Ko'pchilik loyiha umrining oxirigacha Compose'da qoladi — murakkablikni vaqtidan oldin qo'shmang. Kubernetes'ga to'liq 10.8da kiramiz.
2.13. Resurs cheklovlari (memory/CPU limits) va container_name
MUAMMO: bitta servis butun xost xotirasini "yeb" qo'yishi mumkin:
memory leak yoki og'ir so'rov RAM to'ladi BOSHQA servislar ham yiqiladi
"shovqinli qo'shni" (noisy neighbour): bir konteyner butun serverni cho'ktiradi
YECHIM: har servisga RESURS chegarasini belgila (deploy.resources):
services:
app:
build: .
deploy:
resources:
limits: QAT'IY chegara (bundan oshsa cheklanadi)
cpus: "1.5" eng ko'pi 1.5 CPU yadro
memory: 512M eng ko'pi 512 MB RAM (oshsa OOM-kill)
reservations: KAFOLATLANGAN minimum (band qilib qo'yiladi)
cpus: "0.25"
memory: 128M
db:
image: postgres:17-alpine
deploy:
resources:
limits:
memory: 1G DB'ga ko'proq (256 MB shared_buffers + ish)
"deploy.resources.limits" — Compose v2'da (docker compose) SWARM'siz ham
hurmat qilinadi (eski holatda faqat Swarm'da ishlardi — endi lokal ham)
ESKI muqobil (hali ishlaydi): mem_limit: 512m, cpus: 1.5 (top-level, deploy'siz)Resurs cheklovlari — production'da majburiy himoya. Muammo: standart holatda konteyner xost resurslarini (RAM, CPU) cheklovsiz ishlatadi — bitta servisda xotira sizishi (memory leak) yoki og'ir so'rov butun serverning RAM'ini to'ldirishi mumkin, natijada boshqa barcha servislar ham yiqiladi (bu "noisy neighbour" — shovqinli qo'shni muammosi). Yechim — har servisga
deploy.resourcesorqali chegara:limits— qat'iy shift (memory: 512M— bundan oshsa konteyner OOM-kill qilinadi;cpus: "1.5"— CPU vaqti cheklanadi),reservations— kafolatlangan minimum (Docker shu resursni o'sha servisga band qilib qo'yadi). Muhim nuance:deploy.resources.limitsilgari faqat Docker Swarmda ishlar edi, lekin zamonaviydocker compose(v2) uni oddiyupda ham hurmat qiladi. Eski muqobil hali qo'llab-quvvatlanadi:mem_limit: 512mvacpus: 1.5(top-level,deploysiz).container_name— konteynerga qat'iy nom berish (container_name: my-app): standart holatda Compose nom generatsiya qiladi (loyiha-app-1), aniq nom debug'ni osonlashtiradi, lekinscale2.10-bob bilan ziddiyatli (uch nusxa bir xil nomga ega bo'lolmaydi) — shu sabab miqyoslanadigan servisda ishlatmang.
3. Sintaksis — tez ma'lumotnoma
ASOSIY 2.1-bob: docker compose up -d | docker compose down | docker compose down -v
HOLAT: docker compose ps servislar holati
docker compose logs -f app jonli loglar (-f = follow)
docker compose top jarayonlar
QURISH: docker compose build image'larni qur | --no-cache (toza)
docker compose up --build qurib + ishga tushir
BOSHQARISH: docker compose stop | start | restart | rm
ICHIGA KIRISH: docker compose exec app sh ishlayotgan servisga (10.3: Misol 6)
docker compose run app npm test yangi vaqtinchalik konteynerda
SCALE 2.10-bob: docker compose up --scale app=3
PROFIL 2.8-bob: docker compose --profile debug up | COMPOSE_PROFILES=debug ...
FAYL 2.9-bob: docker compose -f compose.yaml -f compose.prod.yaml up
YAML KALITLAR (2.3-6): services | image/build | ports | environment | env_file
volumes | depends_on(condition) | healthcheck(test,interval,retries) | networks
restart | profiles | command | container_name ; top-level: networks, volumes
RESURS 2.13-bob: deploy.resources.limits(cpus, memory) / reservations | mem_limit
MULTI-STAGE 2.11-bob: FROM x AS builder | COPY --from=builder /src /dst | --target=x
CACHE MOUNT (Misol 6b): RUN --mount=type=cache,target=/root/.npm npm ci4. Batafsil kod namunalari
Misol 1 — Oddiy compose.yaml (app + postgres)
# compose.yaml — eng oddiy ikki servisli ilova (app + DB)
# "version:" yozMA — eskirgan (2.2)
services:
app:
build: . # joriy papkadagi Dockerfile'dan qur (2.3)
ports:
- "3000:3000" # XOST:KONTEYNER (10.3: 2.8)
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://app:secret@db:5432/mydb # host=db (servis nomi — 2.4)
depends_on:
- db # db AVVAL ishga tushadi (lekin tartib ≠ tayyor — 2.6)
db:
image: postgres:17-alpine # tayyor image (registry — 2.3)
environment:
- POSTGRES_USER=app
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data # DB ma'lumoti named volume'da (2.5)
volumes:
pgdata: # named volume'ni e'lon qil (2.5)Misol 2 — env_file bilan (sozlamalarni faylga ajratish — 2.7)
# compose.yaml — sozlamalar .env faylda (compose.yaml umumiy bo'lib qoladi)
services:
app:
build: .
ports:
- "${APP_PORT}:3000" # ${...} host .env'dan interpolatsiya (2.7)
env_file:
- .env # .env'dagi HAMMA o'zgaruvchi konteynerga (2.7)
depends_on:
- db
db:
image: postgres:17-alpine
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} # ${...} host .env'dan
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:# .env (compose.yaml yonida — .gitignore'ga qo'sh, Git'ga tushmasin — 10.11)
APP_PORT=3000
POSTGRES_PASSWORD=secret
DATABASE_URL=postgres://app:secret@db:5432/mydb
# .env.example (bo'sh shablon) — bu Git'ga tushadi (jamoaga namuna)Misol 3 — healthcheck + depends_on condition (DB tayyorligini kut — 2.6)
# compose.yaml — app DB HAQIQATAN tayyor bo'lgunicha kutadi (connection refused yo'q)
services:
app:
build: .
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy # db HEALTHY bo'lgunicha KUT (2.6)
redis:
condition: service_started # redis faqat ishga tushsa kifoya
db:
image: postgres:17-alpine
environment:
- POSTGRES_PASSWORD=secret
healthcheck: # DB sog'ligini tekshir (10.3: 2.5)
test: ["CMD-SHELL", "pg_isready -U postgres"] # qabul qilishga tayyormi?
interval: 5s # har 5s tekshir
timeout: 3s # 3s javob bermasa — fail
retries: 5 # 5 marta fail unhealthy
start_period: 10s # dastlabki 10s grace (init uchun)
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
pgdata:Misol 4 — To'liq stack: Nginx + app + db (real production tuzilma)
# compose.yaml — Nginx (oldida) app db (+redis): to'liq real stack
services:
nginx:
image: nginx:1.27-alpine
ports:
- "80:80" # FAQAT Nginx tashqariga ochiq (80/443)
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro # config (bind mount, ro=faqat o'qish)
depends_on:
- app
networks:
- frontend
app:
build: .
environment:
- DATABASE_URL=postgres://app:secret@db:5432/mydb # host=db (2.4)
- REDIS_URL=redis://redis:6379 # host=redis (2.4)
depends_on:
db:
condition: service_healthy # DB tayyor bo'lgunicha kut (2.6)
networks:
- frontend # Nginx bilan (tashqi)
- backend # db/redis bilan (ichki)
# app'da "ports" YO'Q — tashqariga ochilmaydi, Nginx orqali kiriladi
db:
image: postgres:17-alpine
environment:
- POSTGRES_USER=app
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
retries: 5
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- backend # faqat ichki — Nginx ko'rmaydi (2.10)
redis:
image: redis:7-alpine
networks:
- backend
volumes:
pgdata:
networks:
frontend: # Nginx app
backend: # app db/redis (ajratilgan — xavfsiz — 2.10)Misol 5 — Multi-stage Dockerfile: Node build prod (2.11)
# Dockerfile — multi-stage: build vositalari final image'da QOLMAYDI
# syntax=docker/dockerfile:1
# ─────────── 1-BOSQICH: BUILDER (quradi) ───────────
FROM node:22-alpine AS builder # "builder" deb nomlaymiz (2.11)
WORKDIR /app
COPY package*.json ./
RUN npm ci # HAMMA qaramlik (devDeps ham — build kerak)
COPY . .
RUN npm run build # dist/ hosil bo'ladi (TSJS yoki bundler)
# ─────────── 2-BOSQICH: RUNTIME (faqat ishlatadi) ───────────
FROM node:22-alpine # YANGI, toza image (build vositalari yo'q)
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev && \ # FAQAT production qaramlik (10.3: 2.10)
npm cache clean --force # cache tozalash (bitta layer)
COPY --from=builder /app/dist ./dist # builder'dan FAQAT natija (2.11)
USER node # non-root (10.3: 2.11)
EXPOSE 3000
CMD ["node", "dist/main.js"] # exec shakl (10.3: 2.6)
# Natija: ~150 MB (bitta stage ~400 MB o'rniga) — build vositalari TASHLANDIMisol 6 — Multi-stage NestJS (TypeScript build — 8.1)
# Dockerfile — NestJS uchun multi-stage (nest build dist/)
# syntax=docker/dockerfile:1
FROM node:22-alpine AS builder # build bosqichi
WORKDIR /app
COPY package*.json ./
RUN npm ci # @nestjs/cli, TS, devDeps — build uchun
COPY . .
RUN npm run build # "nest build" dist/ (7.1, 8.1)
FROM node:22-alpine # toza runtime bosqichi
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev # faqat production (TS/cli QOLMAYDI)
COPY --from=builder /app/dist ./dist # faqat kompilyatsiya natijasi
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]
# @nestjs/cli (~katta), TypeScript, manba kod — final image'da YO'Q
# Faqat dist/ (JS) + production node_modules kichik, xavfsizMisol 6b — Cache mount + target (build tezligi va uch bosqich — 2.11)
# Dockerfile — cache mount (npm cache'ni layer'lar orasida saqlab, build TEZlashadi)
# + uch bosqich: deps build test production
# syntax=docker/dockerfile:1
# ─── 1) DEPS: qaramliklarni cache mount bilan o'rnat ───
FROM node:22-alpine AS deps
WORKDIR /app
COPY package*.json ./
# --mount=type=cache: npm'ning global cache'i BUILD'lar orasida saqlanadi
# keyingi build'da paketlar qayta yuklanmaydi (tarmoqsiz, tez)
RUN --mount=type=cache,target=/root/.npm \
npm ci
# ─── 2) BUILD: kompilyatsiya (deps'dan node_modules olib) ───
FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build # dist/ hosil bo'ladi
# ─── 3) TEST: alohida bosqich (CI shu bosqichgacha quradi — 10.5) ───
FROM build AS test
RUN npm run test # test o'tmasa — build TO'XTAYDI
# ─── 4) PRODUCTION: toza runtime (test'ni chetlab, faqat natija) ───
FROM node:22-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci --omit=dev # cache mount bu yerda ham tezlashtiradi
COPY --from=build /app/dist ./dist # faqat natija (test bosqichi chetda qoladi)
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]
# TARGET bilan istalgan bosqichgacha qurish mumkin:
# docker build --target test . faqat test bosqichgacha (CI)
# docker build --target production . final (default: oxirgi bosqich)
# docker build --target build . dev/debug (dist/ + devDeps ichida)Misol 7 — compose.override (dev) va prod fayl (2.9)
# compose.yaml — BAZA (umumiy, har ikki muhitda bir xil)
services:
app:
build:
context: .
target: builder # multi-stage'dagi bosqich (2.11, 2.9)
depends_on:
db:
condition: service_healthy
db:
image: postgres:17-alpine
environment:
- POSTGRES_PASSWORD=secret
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 5s
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:# compose.override.yaml — DEV (avtomatik qo'shiladi — 2.9)
services:
app:
ports:
- "3000:3000" # dev'da to'g'ridan ochiq (Nginx yo'q)
volumes:
- ./src:/app/src # bind mount — hot-reload (10.3: 2.7)
command: npm run start:dev # watch rejim
environment:
- NODE_ENV=developmentdocker compose up # baza + override (DEV — avtomatik)
docker compose -f compose.yaml -f compose.prod.yaml up -d # baza + PROD (2.9)Misol 8 — networks bilan ajratish (xavfsizlik — 2.10)
# compose.yaml — db backend tarmoqda (tashqi/nginx tarmog'idan ko'rinmaydi)
services:
nginx:
image: nginx:1.27-alpine
ports: ["80:80"]
networks: [frontend] # faqat frontend
app:
build: .
networks: [frontend, backend] # ko'prik (ikkalasida — 2.10)
db:
image: postgres:17-alpine
environment: [POSTGRES_PASSWORD=secret]
networks: [backend] # faqat backend — nginx to'g'ridan ulanolmaydi
volumes: [pgdata:/var/lib/postgresql/data]
networks:
frontend: # nginx app
backend: # app db (ajratilgan)
volumes:
pgdata:Misol 9 — profiles (dev vositalari — 2.8)
# compose.yaml — pgAdmin va seeder faqat kerak bo'lganda (profil bilan)
services:
app:
build: . # profilsiz — DOIM ishlaydi
depends_on: [db]
db:
image: postgres:17-alpine
environment: [POSTGRES_PASSWORD=secret]
pgadmin:
image: dpage/pgadmin4
ports: ["5050:80"]
profiles: [debug] # faqat "debug" profilda (2.8)
environment:
- PGADMIN_DEFAULT_EMAIL=admin@admin.com
- PGADMIN_DEFAULT_PASSWORD=admin
seeder:
build: .
command: npm run seed # DB'ni test ma'lumot bilan to'ldir
depends_on:
db:
condition: service_healthy
profiles: [tools] # faqat "tools" profildadocker compose up # app + db (profilsizlar)
docker compose --profile debug up # + pgadmin (DB ni brauzerda ko'rish)
docker compose --profile tools run seeder # seed'ni bir marta ishlatishMisol 10 — docker compose buyruqlari to'plami (kundalik ish oqimi)
# === KO'TARISH / TO'XTATISH ===
docker compose up -d # butun stack'ni FONDA ko'tar (-d = detached)
docker compose up --build # avval image'larni qayta qur, keyin ko'tar
docker compose down # to'xtatib, konteyner/tarmoqni o'chir (volume QOLADI)
docker compose down -v # volume ham o'chir (DB KETADI — ehtiyot — 2.5)
# === HOLAT / LOG (debug — 10.3: Misol 6) ===
docker compose ps # servislar holati (Up? healthy?)
docker compose logs -f app # app servisining JONLI loglari (-f = follow)
docker compose logs --tail 50 # barcha servis, oxirgi 50 qator
# === ICHIGA KIRISH ===
docker compose exec app sh # ishlayotgan app konteynerga kir (10.3: Misol 6)
docker compose exec db psql -U app mydb # DB'ga to'g'ridan (psql — 6.6)
docker compose run app npm test # YANGI vaqtinchalik konteynerda test
# === QURISH / TOZALASH ===
docker compose build --no-cache app # app image'ni toza qayta qur (cache'siz)
docker compose restart app # faqat app'ni qayta ishga tushir
docker compose config # yakuniy birlashgan compose'ni ko'r (override + baza)5. To'g'ri va noto'g'ri holatlar
1) Servisga ulanish manzili (DNS — 2.4)
DATABASE_URL=postgres://localhost:5432/db (localhost = o'sha konteyner!)
DATABASE_URL=postgres://db:5432/db (db = servis nomi — Compose DNS)2) DB tayyorligi (depends_on — 2.6)
depends_on: [db] (faqat tartib — DB hali init qilyapti connection refused)
depends_on: { db: { condition: service_healthy } } + healthcheck3) DB ma'lumotini saqlash (2.5)
db servisida volume yo'q (down/up qilsa — ma'lumot YO'QOLADI)
volumes: [pgdata:/var/lib/postgresql/data] + top-level volumes (named)4) version maydoni (2.2)
version: "3.8" (eskirgan — obsolete, ogohlantirish chiqaradi)
to'g'ridan "services:" dan boshla (version YO'Q — 2026)5) Maxfiy ma'lumot (2.7)
parol/kalit to'g'ridan compose.yaml'da + Git'ga push (sir tarqaydi)
.env faylda (${VAR}) + .gitignore'da .env (10.11)6) Image hajmi (multi-stage — 2.11)
bitta stage: build vositalari (TS, cli) final image'da (~400 MB)
multi-stage: COPY --from=builder /app/dist (faqat natija — ~150 MB)7) Tashqariga ochiq portlar (2.10)
db'da ports: ["5432:5432"] (DB internetdan ko'rinadi — xavf)
db portsiz, faqat backend tarmoqda; tashqariga faqat Nginx (80/443)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — App DB'ga ulanolmaydi: connection refused / ECONNREFUSED
Sababi: depends_on: [db] faqat tartibni beradi — DB konteyneri ko'tarildi, lekin hali initsializatsiya qilyapti va ulanishni qabul qilmaydi 2.6-bob. Yechimi: DB'ga healthcheck (pg_isready) qo'shing, app'da depends_on: { db: { condition: service_healthy } } yozing (Misol 3). Ilovada ham qayta urinish (retry) mantig'i foydali.
Xato 2 — App localhostga ulanmoqchi bo'lib topolmaydi
Sababi: ilova DATABASE_URL=...localhost:5432ni ishlatyapti, lekin DB boshqa konteynerda — localhost app konteynerining o'zini bildiradi 2.4-bob. Yechimi: manzilni servis nomiga o'zgartiring: db:5432 (Compose DNS — 2.4). Lokal kompyuterdan ulansangiz localhost, konteynerlar orasida — servis nomi.
Xato 3 — docker compose down dan keyin DB ma'lumoti yo'qoldi
Sababi: down -v ishlatilgan (volume o'chadi), yoki DB servisida named volume umuman yo'q edi 2.5-bob. Yechimi: named volume qo'shing (Misol 1); oddiy to'xtatishda down (-vsiz) ishlating — volume qoladi. -v faqat butunlay toza boshlash kerak bo'lganda.
Xato 4 — version is obsolete ogohlantirishi
Sababi: compose.yamlda eski version: "3.x" qatori bor (2026da eskirgan — 2.2). Yechimi: version: qatorini butunlay o'chiring — faylni to'g'ridan services: dan boshlang.
Xato 5 — port is already allocated / bind: address already in use
Sababi: portsdagi xost porti (masalan 3000) boshqa jarayon/konteyner tomonidan band (10.3: Xato 5). Yechimi: docker compose ps va ss -tulpn (10.1: 2.7) bilan kim band qilganini toping; eski stack'ni docker compose down bilan to'xtating; yoki boshqa xost port bering ("3001:3000").
Xato 6 — ${VAR} qiymati bo'sh / interpolatsiya ishlamayapti
Sababi: .env fayli compose.yaml yonida emas, yoki o'zgaruvchi nomi noto'g'ri, yoki bo'sh 2.7-bob. Yechimi: .envni compose.yaml yoniga qo'ying; docker compose config bilan yakuniy qiymatlarni tekshiring (interpolatsiya natijasini ko'rsatadi). Default berish: ${VAR:-default}.
Xato 7 — Build cache ishlamay, har safar to'liq qayta quriladi
Sababi: Dockerfile tartibi noto'g'ri (COPY . . npm cidan oldin), yoki --no-cache doim ishlatilyapti (10.3: 2.3, Xato 2). Yechimi: cache-optimal tartib (package fayllar avval — 10.3: Misol 1); multi-stage'da ham har bosqichda shu qoida. --no-cache faqat zarur bo'lganda.
Xato 8 — COPY --from=builder "not found" yoki bo'sh
Sababi: bosqich nomi noto'g'ri (AS builder deb nomlanmagan), yoki manba yo'l xato (builder'da dist/ boshqa joyda — 2.11). Yechimi: FROM ... AS builder nomini tekshiring; builder'da WORKDIR /app va RUN npm run build dist/ ni qayerga chiqarganini aniqlang; COPY --from=builder /app/dist ./dist yo'llari mos kelsin.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Docker 10.3-bob: Compose —
docker runlarni avtomatlashtiradi; servisbuildDockerfile'dan; multi-stage — Dockerfile texnikasi. - Nginx 10.2-bob: Compose'da
nginxservisi — app oldida reverse proxy; config bind mount bilan. - Linux server 10.1-bob:
restartsiyosati systemd g'oyasi 2.6-bob; tarmoq ajratish — least exposure 2.7-bob. - CI/CD 10.5-bob: GitHub Actions multi-stage image quradi,
docker composeni serverda ishlatadi. - AWS 10.6-bob: Compose lokal/kichik server uchun; katta miqyosda ECS/EKS.
- PostgreSQL/MongoDB (6.x):
dbservisi + named volume;pg_isreadyhealthcheck. - Redis 5.21-bob:
redisservisi — cache/sessiya; appredis://redis:6379bilan ulanadi. - NestJS 8.1-bob: multi-stage build (
nest builddist/— Misol 6); env config 8.14-bob. - Secrets 10.11-bob:
.envGit'dan tashqarida;${VAR}interpolatsiya; secret boshqaruvi. - Kubernetes 10.8-bob: Compose'dan keyingi qadam — katta miqyos orkestratsiyasi 2.12-bob.
8. Eng yaxshi amaliyotlar (best practices)
version:yozma (eskirgan — to'g'ridanservices:— 2.2).- Servis nomi bilan ulan (
db:5432,localhostemas — Compose DNS — 2.4). - DB'ga
healthcheck+service_healthy(depends_ontartibi yetarli emas — 2.6). - DB ma'lumoti named volume'da (
downda yo'qolmasin;-vdan ehtiyot — 2.5). - Multi-stage build (build vositalari final image'da qolmasin — 2.11).
- Tarmoq ajratish (DB faqat backend tarmoqda; tashqariga faqat Nginx — 2.10).
.env+${VAR}(maxfiy ma'lumot fayl/Git'dan tashqarida — 2.7, 10.11).restart: unless-stopped(server qayta yuklansa servis o'zi ko'tarilsin — 2.3).- override bilan dev/prod (umumiy baza + farqlar override'da — DRY — 2.9).
docker compose config(deploy oldidan yakuniy birlashgan faylni tekshir — Misol 10).profiles(dev vositalari pgAdmin/seeder — production'da ko'tarilmasin — 2.8).- Resurs cheklovi (production'da
deploy.resources.limits— bitta servis butun serverni cho'ktirmasin — 2.13). - Cache mount (build tezligi uchun
--mount=type=cache— qaramliklar qayta yuklanmasin — Misol 6b). - Aniq image tag (
postgres:17-alpine,latestemas — barqaror — 10.3: 2.11).
9. Amaliy loyiha: "To'liq Stack'ni Compose bilan Orkestrlash"
NestJS (yoki Express) ilovasini PostgreSQL, Redis va Nginx bilan birga bitta compose.yaml orqali ko'tarish — har bir backendchining kundalik ko'nikmasi.
Maqsad
10.3da Dockerlashtirgan ilovangni endi to'liq stack sifatida ishga tushir: app + PostgreSQL (volume bilan) + Redis + Nginx (oldida), hammasi compose.yamlda, multi-stage build bilan kichik image, healthcheck bilan to'g'ri tartib, va dev/prod uchun override.
Talablar (requirements)
- compose.yaml:
app(build),db(postgres:17-alpine),redis(redis:7-alpine),nginxservislari —version:siz (Misol 1, 4, 2.2). - Multi-stage Dockerfile: builder (build) + runtime (toza) bosqichlar; image ~150 MB (Misol 5/6, 2.11).
- Networking: app DB'ni nomi bilan topsin (
db:5432,redis:6379— 2.4). - Named volume: Postgres ma'lumoti
pgdatavolume'da —down/upda saqlansin (Misol 1, 2.5). - healthcheck + condition: db'ga
pg_isready, appcondition: service_healthybilan kutsin (Misol 3, 2.6). - env_file: parol/URL
.envda,${VAR}interpolatsiya;.env.gitignoreda,.env.exampleGit'da (Misol 2, 2.7). - Tarmoq ajratish: db/redis faqat
backendtarmoqda; tashqariga faqat Nginx (80) (Misol 8, 2.10). - Nginx: reverse proxy app oldida (config bind mount); app
portssiz (Misol 4, 10.2). - override:
compose.override.yaml(dev — bind mount, hot-reload) +compose.prod.yaml(Misol 7, 2.9). - profiles:
pgadmin(debug profil) — DB'ni brauzerda ko'rish uchun (Misol 9, 2.8).
Maslahatlar (hint)
appdaportsqo'ymang (Nginx orqali kiriladi) — faqat dev override'da ochiq (2.10, Misol 7).- DB'ga ulanish manzili
localhostemas,db(servis nomi) — eng keng xato (2.4, Xato 2). depends_on: [db]yetarli emas —healthcheck+service_healthy(aks holda connection refused — 2.6, Xato 1).docker compose configbilan override birlashganini va${VAR}to'lganini tekshiring (Misol 10, Xato 6).docker compose down(volume qoladi) vsdown -v(DB ketadi) farqini esda tuting (2.5, Xato 3).- Image hajmini solishtiring: bitta stage vs multi-stage (
docker images— 2.11).
"Tayyor" mezonlari (acceptance criteria)
-
docker compose up -dbutun stack'ni (app+db+redis+nginx) bir buyruqda ko'taradi. -
http://localhost(Nginx, 80) orqali ilova javob beradi (app'ga to'g'ridan kirilmaydi). - App DB va Redis'ni nomi bilan topadi (ulanish ishlaydi).
-
docker compose downso'ngupqilinganda DB ma'lumoti saqlanib qoladi (volume). - App DB tayyor bo'lguncha kutadi (connection refused yo'q — healthcheck).
-
.envGit'da yo'q;compose.yamlda ochiq parol yo'q. - db/redis tashqariga ochiq emas (
docker compose ps— faqat Nginx porti). - Multi-stage image bitta stage'dan sezilarli kichik (
docker images). -
docker compose --profile debug uppgAdmin'ni qo'shadi. - dev (
up) va prod (-f ... -f compose.prod.yaml) har xil sozlama bilan ishlaydi.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda ko'p konteynerli ilovani boshqarishni va image hajmini optimallashtirishni o'rgandik:
- Compose nima (ko'p konteyner muammosi — 2.1); compose.yaml anatomiyasi (services/networks/volumes — 2.2); service ta'rifi (image vs build, ports, env — 2.3).
- Tarmoq (avtomatik DNS — servis nomi = hostname — 2.4); named volume (DB ma'lumoti — 2.5); depends_on + healthcheck (DB tayyorligi — 2.6); env/.env (interpolatsiya — 2.7).
- profiles (shartli servis — 2.8); override (dev/prod — 2.9); networks ajratish + scale 2.10-bob; multi-stage build (kichik image, cache mount, target — 2.11); Compose vs Kubernetes 2.12-bob; resurs cheklovlari (limits/reservations — 2.13).
Endi siz butun tizimni — ilova, DB, Redis, Nginx — bitta faylga yozib, bir buyruqda ko'tara olasiz, va multi-stage bilan production image'ni bir necha barobar kichraytirasiz. Bu — lokal development va kichik/o'rta deploy'ning markaziy ko'nikmasi.
Keyingi bob — 10.5-bob: CI/CD (GitHub Actions) — pipeline, avtomatik test/deploy. Hozir image quramiz va Compose bilan qo'lda ko'taramiz. Lekin har o'zgarishda qo'lda test qilish, image qurish, registry'ga push qilish, serverga ulanib deploy qilish — bu takror va xatoga moyil. CI/CD buni avtomatlashtiradi: kod Git'ga push qilinishi bilan GitHub Actions o'zi testlarni ishga tushiradi, multi-stage image quradi, registry'ga yuboradi va serverda docker composeni yangilaydi — odam aralashuvisiz. Bu — zamonaviy jamoaviy ishlab chiqishning yuragi.
Foydalanilgan rasmiy/ishonchli manbalar
- Docker Docs — "Docker Compose overview" (docs.docker.com/compose — services/networks/volumes,
docker composev2 CLI, 2026) - Docker Docs — Compose file reference / compose-spec (services, depends_on condition, healthcheck, env_file, profiles;
versionobsolete — docs.docker.com/reference/compose-file) - Docker Docs — "Multi-stage builds" (FROM ... AS, COPY --from, --target — docs.docker.com/build/building/multi-stage)
- Docker Docs — "Use Compose profiles" va override/merge (docs.docker.com/compose/how-tos/profiles, multiple-compose-files)
- Compose Specification (compose-spec.io) — rasmiy spetsifikatsiya (2026)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!