10 β Volume va Docker tarmog'i¶
β¬ οΈ Oldingi: 09 β Image optimizatsiya va registry Β· π README Β· Keyingi: 11 β Docker Compose β‘οΈ
Bu bobda: konteyner o'chganda ma'lumotning yo'qolishi muammosini (ephemeral fayl tizimi) hal qilamiz β volume turlari (named volume, bind mount, tmpfs),
-vva--mountsintaksisi,docker volume create/ls/inspect/rm/prune; haqiqiy postgres konteyneriga jadval yozib, konteynerni o'chirib qayta yaratganda ma'lumot saqlanishini ko'rsatamiz; so'ng Docker network β default bridge va user-defined bridge farqi (ichki DNS bilan konteynerlar bir-birini nom orqali topishi),host/nonerejimlar,docker network create/ls/inspect/connect, hamda port publish (-p) bilan ichki tarmoq aloqasi orasidagi xavfsizlik farqi.
Muammo: konteyner o'chsa, ma'lumot yo'qoladi¶
Tasavvur qiling: postgres'ni konteynerda ishga tushirdingiz, ichiga jadval va yuzlab qator yozdingiz. Ertasi kuni image'ni yangilamoqchi bo'lib konteynerni o'chirib (docker rm) qayta yaratdingiz β va hamma ma'lumot yo'q. Bo'sh baza. Bu sizning xatoyingiz emas: bu Docker'ning ataylab qilingan dizayni.
Konteynerning fayl tizimi ephemeral (o'tkinchi) β u image qatlamlari ustiga qo'shilgan ingichka "writable layer"da yashaydi. Konteyner o'chsa, shu qatlam ham o'chadi. Bu image'lar uchun zo'r (toza, takrorlanadigan), lekin ma'lumotlar bazasi, yuklangan fayllar, loglar uchun halokat.
docker run -d --name baza -e POSTGRES_PASSWORD=test postgres:16-alpine
# ... ichiga ma'lumot yozdingiz ...
docker rm -f baza # konteyner o'chdi
docker run -d --name baza -e POSTGRES_PASSWORD=test postgres:16-alpine
# baza BO'SH β ma'lumot yo'q
π Asosiy qoida: saqlanishi kerak bo'lgan har qanday ma'lumotni konteyner ichida QOLDIRMANG. Uni konteynerdan tashqaridagi doimiy joyga β volume'ga chiqaring. Konteyner β o'tkinchi, volume β doimiy.
Yechim: konteyner ichidagi muayyan papkani (masalan postgres uchun /var/lib/postgresql/data) konteyner umridan mustaqil yashaydigan saqlash joyiga ulaymiz. Bu joy β volume.
Volume turlari¶
Docker'da ma'lumotni saqlashning uch yo'li bor. Quyidagi diagramma uchovi host (asosiy kompyuter) fayl tizimi va xotirasiga qanday bog'lanishini ko'rsatadi.
1. Named volume β afzal yo'l¶
Named volume (nomlangan volume) β Docker o'zi boshqaradigan, nomi bor saqlash joyi. Docker uni host'da maxsus papkada saqlaydi (Linux'da /var/lib/docker/volumes/<nom>/_data) va siz to'g'ridan-to'g'ri papka yo'lini bilishingiz shart emas β faqat nom bilan murojaat qilasiz.
docker volume create maydonlar # named volume yaratish
docker run -d --name baza \
-e POSTGRES_PASSWORD=test \
-v maydonlar:/var/lib/postgresql/data \
postgres:16-alpine
Bu yerda -v maydonlar:/var/lib/postgresql/data degani: maydonlar nomli volume'ni konteyner ichidagi /var/lib/postgresql/data papkaga ula. Postgres shu papkaga yozadi β demak hamma ma'lumot volume'ga tushadi.
π‘ Afzal yo'l shu. Production'da, ayniqsa DB uchun, named volume ishlating. Docker uni boshqaradi (huquqlar, drayver, backup nuqtasi), host papka strukturasiga bog'lanib qolmaysiz, va boshqa mashinaga ko'chirish osonroq.
2. Bind mount β dev uchun qulay¶
Bind mount β host'dagi aniq papkani konteynerga ulash. Siz host yo'lini o'zingiz ko'rsatasiz:
Bu yerda host'dagi /home/oqil/loyiha/kod papkasi konteyner ichidagi /app ga ulanadi. Host'da faylni tahrirlasangiz, konteyner ichida ham darhol o'zgaradi β shuning uchun bind mount ishlab chiqish (dev) uchun ideal: kodni mahalliy tahrirlaysiz, konteyner darrov ko'radi, qayta build qilish shart emas.
β οΈ Bind mount = host'ga to'g'ridan-to'g'ri ulanish. Konteyner shu papkadagi fayllarni o'chirishi/o'zgartirishi mumkin. Production DB uchun bind mount tavsiya etilmaydi: host yo'liga, huquqlarga va host fayl tizimiga bog'lanib qolasiz. Dev'da kod uchun β a'lo; production ma'lumot uchun β named volume.
π Yo'l ajratish farqi: -v qiymatida nom bo'lsa (maydonlar:/app) β bu named volume; absolyut yo'l bo'lsa (/home/oqil/...:/app yoki .:/app) β bu bind mount. Docker / belgisiga qarab ajratadi.
3. tmpfs β xotirada, vaqtinchalik¶
tmpfs mount β ma'lumotni diskka emas, host'ning operativ xotirasiga (RAM) yozadi. Konteyner o'chsa β yo'qoladi. Bu maxfiy vaqtinchalik fayllar (parol, token kesh) yoki tez, lekin saqlanishi shart bo'lmagan ma'lumot uchun.
βΉοΈ tmpfs faqat Linux host'da ishlaydi. Diskka hech narsa yozilmaydi β tez, lekin doimiy emas.
-v va --mount β ikki sintaksis¶
Volume ulashning ikki yozuvi bor β ikkalasi ham ishlaydi:
# qisqa sintaksis (-v): NAME:TARGET[:OPTIONS]
docker run -v maydonlar:/var/lib/postgresql/data postgres:16-alpine
# aniq sintaksis (--mount): key=value juftliklari
docker run --mount type=volume,source=maydonlar,target=/var/lib/postgresql/data postgres:16-alpine
Farqi: --mount batafsil va aniq (har bir parametr nomi bilan: type, source, target, readonly), -v esa qisqa. Docker rasmiy hujjatlari yangi loyihalar uchun --mountni tavsiya qiladi (xatoga kam yo'l qo'yadi), lekin amaliyotda -v hamon eng ko'p ishlatiladi. Misol uchun readonly (faqat o'qish):
docker run --mount type=volume,source=konfig,target=/etc/app,readonly nginx:1.27-alpine
# -v ekvivalenti: -v konfig:/etc/app:ro
Volume buyruqlari¶
docker volume create maydonlar # yaratish
docker volume ls # barcha volume'lar ro'yxati
docker volume inspect maydonlar # batafsil (jumladan host'dagi joyi)
docker volume rm maydonlar # o'chirish (foydalanilmayotgan bo'lsa)
docker volume prune # foydalanilmayotgan barcha volume'larni tozalash
docker volume inspect ma'lumot qayerda yotganini ko'rsatadi:
β οΈ
docker volume pruneehtiyot bo'lib ishlating. U hech bir konteyner ishlatmayotgan volume'larni o'chiradi β undagi ma'lumot bilan birga. Agar konteyner vaqtincha o'chgan, lekin volume keyin kerak bo'lsa,pruneuni ham yo'q qilishi mumkin.-a(--all) bayrog'i esa nom berilgan volume'larni ham o'chiradi. Production'da o'ylab ishlating.
π Muhim nuqta: docker rm konteyner konteyner bilan bog'langan named volume'ni o'chirmaydi β shuning uchun ma'lumot saqlanadi. Volume'ni faqat docker volume rm yoki docker rm -v (anonim volume'lar uchun) o'chiradi.
Amaliyot: postgres ma'lumoti konteynerdan omon qoladi¶
Endi eng muhim isbotni qilamiz: konteynerni o'chirib qayta yaratsak ham, named volume'dagi ma'lumot saqlanib qoladi. Quyidagi qadamlar haqiqatan lokal Docker'da sinab ko'rilgan.
Quyidagi diagramma volume "umr chizig'i"ni ko'rsatadi: konteyner o'chib qayta yaralsa ham, volume va undagi ma'lumot joyida qoladi.
1-qadam β volume yarating va postgres'ni ulang:
docker volume create dvo10vol
docker run -d --name dvo10pg \
-e POSTGRES_PASSWORD=test \
-v dvo10vol:/var/lib/postgresql/data \
postgres:16-alpine
Postgres tayyor bo'lishini kuting (bir necha soniya), keyin tekshiring:
2-qadam β jadval yarating va qator yozing:
docker exec dvo10pg psql -U postgres -c \
"CREATE TABLE vazifalar (id serial PRIMARY KEY, matn text);"
docker exec dvo10pg psql -U postgres -c \
"INSERT INTO vazifalar (matn) VALUES ('volume sinovi'), ('ikkinchi qator');"
docker exec dvo10pg psql -U postgres -c "SELECT * FROM vazifalar;"
3-qadam β konteynerni butunlay o'chiring:
Konteyner endi yo'q. Lekin volume omon: docker volume ls da dvo10vol hali turibdi.
4-qadam β SHU volume bilan yangi konteyner yarating va ma'lumotni tekshiring:
docker run -d --name dvo10pg \
-e POSTGRES_PASSWORD=test \
-v dvo10vol:/var/lib/postgresql/data \
postgres:16-alpine
# tayyor bo'lguncha kuting...
docker exec dvo10pg psql -U postgres -c "SELECT * FROM vazifalar;"
Ma'lumot joyida! Konteyner yangi, lekin jadval va ikkala qator saqlanib qoldi β chunki ular konteynerda emas, volume'da yashagan. Aynan shu narsa production DB uchun hayotiy.
Tozalash (mashqdan keyin):
π‘ Sir: image'ni yangilash (masalan
postgres:16-alpinedan keyingi versiyaga o'tish) β volume tufayli xavfsiz: eski konteynerni o'chirasiz, yangi image bilan qayta yaratasiz, ma'lumot o'sha volume'dan keladi. Konteyner β almashtiriladigan qism, volume β qadrli yadro.
Docker network: konteynerlar qanday gaplashadi¶
Ilovangiz odatda yolg'iz emas: web konteyner db konteynerga, db esa cache (redis) ga ulanishi kerak. Ular bir-birini qanday topadi? Docker har bir konteynerga IP beradi, lekin IP har ishga tushganda o'zgarishi mumkin β IP'ga bog'lanib qolish mo'rt. Yechim β Docker network va undagi ichki DNS.
Tarmoq turlari (drayverlari):
| Tur | Tavsif | Qachon |
|---|---|---|
| bridge (default) | Standart yakka-host tarmog'i. Yangi konteyner avtomatik shu yerga tushadi. | Oddiy holatlar |
| user-defined bridge | O'zingiz yaratgan bridge β ichki DNS bor (konteyner nomi bilan topiladi). | Ko'p-konteynerli ilova β afzal |
| host | Konteyner host'ning tarmog'ini to'g'ridan-to'g'ri ishlatadi (izolyatsiya yo'q). | Maxsus, yuqori unumdorlik kerak bo'lsa |
| none | Tarmoq umuman yo'q (to'liq izolyatsiya). | Tarmoqsiz ishlash kerak bo'lsa |
Default bridge vs user-defined bridge β eng muhim farq¶
Bu bobning eng muhim nuqtasi. Default bridge'da konteynerlar bir-birini faqat IP orqali topadi β nom bilan emas. User-defined bridge'da esa Docker o'rnatilgan DNS server ishga tushiradi: konteynerlar bir-birini nom orqali topadi.
# β ESKI / ZAIF USUL: default bridge β nom bilan topilmaydi
docker run -d --name db alpine sleep 600
docker run -d --name app alpine sleep 600
docker exec app ping db # XATO: "bad address 'db'" β nom yechilmaydi
# β
TO'G'RI: user-defined bridge β nom bilan topiladi
docker network create mreja
docker run -d --name db --network mreja alpine sleep 600
docker run -d --name app --network mreja alpine sleep 600
docker exec app ping db # ISHLAYDI: db nomi IP'ga yechiladi
Quyidagi diagramma user-defined bridge'dagi ichki DNS'ni ko'rsatadi: app konteyner db konteynerni IP emas, nom orqali topadi.
π Qoida: ko'p-konteynerli ilova qursangiz, HAR DOIM user-defined bridge yarating va konteynerlarni shunga ulang. Shunda ulanish manzili IP emas, barqaror nom bo'ladi (
postgres://db:5432,redis://cache:6379). IP'ni hech qachon qo'lda yozmang. (11-bobdagi Docker Compose buni avtomatik qiladi.)
Network buyruqlari¶
docker network create mreja # user-defined bridge yaratish
docker network ls # tarmoqlar ro'yxati
docker network inspect mreja # batafsil (ulangan konteynerlar, IP'lar)
docker network connect mreja konteyner # ishlab turgan konteynerni tarmoqqa ulash
docker network disconnect mreja konteyner # tarmoqdan uzish
docker network rm mreja # o'chirish
docker network prune # foydalanilmayotgan tarmoqlarni tozalash
Amaliyot: ikki konteyner bir-birini nom bilan topadi¶
Quyidagi mashq haqiqatan lokal Docker'da sinab ko'rilgan: bitta tarmoq yaratamiz, ikki konteynerni shunga ulaymiz va biri ikkinchisini nom orqali topishini ko'rsatamiz.
1-qadam β tarmoq yarating:
2-qadam β ikki konteyner shu tarmoqda:
docker run -d --name dvo10db --network dvo10net alpine sleep 600
docker run -d --name dvo10app --network dvo10net alpine sleep 600
3-qadam β app konteyneridan db ni NOM bilan toping:
Nom (dvo10db) IP'ga (172.19.0.2) yechildi β buni Docker'ning ichki DNS'i qildi. Endi ping:
PING dvo10db (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.311 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.084 ms
Teskari yo'nalish ham ishlaydi (db dan app ni topish) β DNS ikki tomonlama.
Tozalash:
π‘ Real ilovada bu shunday ko'rinadi:
appkonteyner kodida ulanish satripostgres://dvo10db:5432/...bo'ladi β IP emas, nom.dbkonteyner qayta yaratilib IP o'zgarsa ham, nom o'zgarmaydi, demak kod ham o'zgarmaydi.
Port publish (-p) vs ichki tarmoq aloqasi β xavfsizlik¶
Endi muhim farqni ajrataylik: ichki konteynerlararo aloqa va tashqi dunyoga port ochish β bular ikki boshqa narsa.
- Ichki aloqa (bir tarmoqdagi konteynerlar) β
-pshart emas. Bir user-defined tarmoqda turgan konteynerlar bir-biriga barcha portlar bo'yicha to'g'ridan-to'g'ri ulanadi.appkonteynerdb:5432ga-psiz ham ulanadi. - Tashqi aloqa (host'dan yoki internetdan konteynerga) β
-p(publish) kerak.-p 8080:80host'ning 8080-portini konteynerning 80-portiga ulaydi.
# faqat ICHKI: db ni publish QILMANG β tashqaridan ko'rinmaydi, faqat tarmoq ichidan
docker run -d --name db --network mreja postgres:16-alpine
# TASHQI: web ni publish qiling β brauzer host:8080 orqali ko'radi
docker run -d --name web --network mreja -p 8080:80 nginx:1.27-alpine
π Xavfsizlik qoidasi: faqat tashqaridan ko'rinishi SHART bo'lgan servislarnigina publish qiling (odatda β web/reverse proxy). Ma'lumotlar bazasi, redis, ichki APIni
-pbilan ochmang β ular faqat ichki tarmoqda yashasin. Agar-p 5432:5432bilan DB'ni ochsangiz, u butun internetga (yoki kamida host tarmog'iga) ochilib qoladi β bu jiddiy xavfsizlik teshigi.
β οΈ Ko'p yangi boshlovchilar "ulanmayapti" deb DB'ni ham publish qilib qo'yadi β bu noto'g'ri yechim. To'g'ri yechim: ikkala konteynerni bir tarmoqqa qo'yish, DB'ni publish qilmaslik, web esa DB'ga nom bilan ulanadi.
βΉοΈ
hosttarmoq rejimida (--network host) konteyner host portlarini to'g'ridan-to'g'ri egallaydi β-pishlamaydi va izolyatsiya yo'qoladi. Bu maxsus holatlar uchun; odatda user-defined bridge + tanlab publish afzal.
10-bob mashqlari¶
Quyidagi buyruqlarni o'zingiz tering va ishga tushiring. Tugagach
docker volume rm/docker network rmbilan tozalashni unutmang.
Oson¶
docker volume create mashq1bilan named volume yarating, so'ngdocker volume lsda ko'ring vadocker volume inspect mashq1 --format '{{.Mountpoint}}'bilan host'dagi joyini toping.- Bitta alpine konteynerni
-v mashq2:/databilan ishga tushiring, ichida/data/salom.txtfayl yarating, konteynerni o'chiring, yangi konteynerni shu volume bilan yarating va fayl saqlanganini tekshiring. -vva--mountfarqini ayting:-vqiymatidadb:/var/lib/...va/home/user/kod:/appdan qaysi biri named volume, qaysi biri bind mount va Docker buni qanday ajratadi?docker network lsni ishga tushiring va default tarmoqlarni (bridge,host,none) toping.docker network create test1bilan tarmoq yarating vadocker network inspect test1 --format '{{.Driver}}'bilan drayveribridgeekanini tasdiqlang.
O'rta¶
- Postgres'ni named volume bilan ishga tushiring, jadval va qator yozing, konteynerni
rm -fqiling, qayta yarating va ma'lumot saqlanganini ko'rsating.
Yechim
docker volume create mashq6
docker run -d --name pg6 -e POSTGRES_PASSWORD=test \
-v mashq6:/var/lib/postgresql/data postgres:16-alpine
# tayyor bo'lguncha kuting
docker exec pg6 pg_isready -U postgres
docker exec pg6 psql -U postgres -c "CREATE TABLE t (id int);"
docker exec pg6 psql -U postgres -c "INSERT INTO t VALUES (42);"
docker rm -f pg6
docker run -d --name pg6 -e POSTGRES_PASSWORD=test \
-v mashq6:/var/lib/postgresql/data postgres:16-alpine
docker exec pg6 psql -U postgres -c "SELECT * FROM t;" # 42 chiqadi
# tozalash:
docker rm -f pg6 && docker volume rm mashq6
- User-defined bridge yarating, ikki alpine konteynerni shunga ulang va biri ikkinchisini
getent hosts <nom>bilan topishini ko'rsating.
Yechim
- Default bridge'da nom bilan ulanish ISHLAMASLIGINI ko'rsating:
--networkbermay ikki konteyner yarating va biridan ikkinchisini nom bilan topib ko'ring.
Yechim
Default bridge'da ichki DNS yo'q, shuning uchun nom yechilmaydi. Aynan shu sabab user-defined bridge afzal.--mountsintaksisi bilan readonly (faqat o'qish) volume ulang va konteyner ichida fayl yozib ko'ring (xato berishi kerak).
Yechim
docker volume create mashq9
# avval ma'lumot yozamiz (yozish ruxsati bilan)
docker run --rm -v mashq9:/data alpine sh -c "echo salom > /data/f.txt"
# endi readonly ulaymiz
docker run --rm --mount type=volume,source=mashq9,target=/data,readonly \
alpine sh -c "cat /data/f.txt; echo yangi > /data/g.txt"
# cat ishlaydi (salom), lekin yozish "Read-only file system" xatosi beradi
docker volume rm mashq9
- Web (nginx) konteynerni
-p 8080:80bilan publish qiling va host brauzeridanhttp://localhost:8080ochib ishlaganini tekshiring. So'ng-psiz qayta ishga tushirib, tashqaridan ko'rinmasligini ko'ring.
Qiyin¶
-
Bitta tarmoqda nginx (
web, publish bilan) va alpine (ichki, publish'siz) yarating.webdanichkini nom bilan toping, lekin host'danichkiga to'g'ridan-to'g'ri ulana olmasligingizni tushuntiring (publish yo'q).Yechim
docker network create m11 docker run -d --name web11 --network m11 -p 8080:80 nginx:1.27-alpine docker run -d --name ichki11 --network m11 alpine sleep 600 # web11 dan ichki11 ni nom bilan topish (ichki aloqa, publish shart emas): docker exec web11 getent hosts ichki11 # IP'ga yechiladi # host brauzeridan web11 ko'rinadi (publish bor): http://localhost:8080 # ichki11 host'dan KO'RINMAYDI β publish yo'q, faqat m11 tarmog'i ichida yashaydi # tozalash: docker rm -f web11 ichki11 && docker network rm m11Xavfsizlik mohiyati:
ichki11(masalan DB rolida) tashqariga ochilmaydi β faqat tarmoq ichidagi konteynerlar unga ulanadi. Faqatweb11publish qilingani uchun internetga ochiq, ichki servislar himoyada. -
Ishlab turgan konteynerni
docker network connectbilan ikkinchi tarmoqqa ham ulang vadocker network inspectorqali konteynerning ikkala tarmoqda turganini tasdiqlang.Yechim
docker network create net-a docker network create net-b docker run -d --name ikkita --network net-a alpine sleep 600 docker network connect net-b ikkita # ikkinchi tarmoqqa qo'shamiz docker inspect ikkita --format '{{json .NetworkSettings.Networks}}' # net-a va net-b ikkalasi ham ko'rinadi docker network inspect net-b --format '{{range .Containers}}{{.Name}}{{end}}' # ikkita # tozalash: docker rm -f ikkita && docker network rm net-a net-bBir konteyner bir nechta tarmoqda bo'lishi mumkin β masalan, reverse proxy ham "frontend", ham "backend" tarmog'ida turishi mumkin.
-
Bind mount bilan dev-loop ko'rsating: host papkasini konteynerga ulang, host'da faylni o'zgartiring va konteyner ichida o'zgarish darhol ko'rinishini tasdiqlang.
Yechim
mkdir -p /tmp/mashq13 && echo "v1" > /tmp/mashq13/data.txt docker run -d --name bind13 -v /tmp/mashq13:/app alpine sleep 600 docker exec bind13 cat /app/data.txt # v1 echo "v2" > /tmp/mashq13/data.txt # host'da o'zgartiramiz docker exec bind13 cat /app/data.txt # v2 β darhol ko'rinadi docker rm -f bind13Bind mount host papkasini "to'g'ridan-to'g'ri oyna" sifatida ulaydi β qayta build yoki ko'chirish shart emas. Shuning uchun dev'da kod uchun ideal.
β¬ οΈ Oldingi: 09 β Image optimizatsiya va registry Β· π README Β· Keyingi: 11 β Docker Compose β‘οΈ