IlmHamroh
JavaScript Full-stack/26-qism. SQL va PostgreSQL3/64-dars19 daqiqa
Mundarija (35)

Docker volume va bind mount: konteynerda ma'lumotni saqlash

Qisqacha: Konteyner o'chirilsa, uning ichiga yozilgan fayllar ham o'chadi. Shuning uchun ma'lumot konteynerdan tashqariga yoziladi: named volume (Docker boshqaradigan nomli saqlash joyi — baza uchun eng yaxshi tanlov), bind mount (kompyuteringizdagi papka konteynerga ulanadi) yoki tmpfs (faqat xotirada, vaqtinchalik). PostgreSQL 18 image'ida volume /var/lib/postgresql ga ulanadi — eski qo'llanmalardagi /var/lib/postgresql/data endi xato beradi.

Bu darsda

  • Konteyner o'chirilganda ma'lumot qayerga ketishini va uni qanday saqlab qolishni tushuntira olasiz.
  • Named volume yaratib, Postgres bazasini konteynerni almashtirgandan keyin ham saqlab qolasiz.
  • PostgreSQL 18 image'idagi yangi volume yo'lini va eski yo'l nima uchun xato berishini bilasiz.
  • Bind mount bilan kompyuterdagi faylni konteynerga berasiz va Windows'dagi ruxsatlar muammosini tushunasiz.
  • Volume zaxirasini olasiz, tmpfs'ni ishlatasiz va docker volume rm xavfini bilasiz.

Oldin bilishingiz kerak: Image, container va registry: asosiy buyruqlar, Fayl ruxsatlari va foydalanuvchilar, Fayl tizimi: papkalar daraxti va fayllar.

1. Nega bu kerak?

Oldingi darsda Postgres konteynerini ishga tushirdingiz, keyin docker rm -f bilan o'chirdingiz. Shunda baza qayerga ketdi? Javob ikki xil bo'lishi mumkin:

  • Konteynerning o'z yoziladigan qatlamiga yozilgan bo'lsa — konteyner bilan birga yo'qoladi.
  • postgres image'ida esa baza papkasi VOLUME deb e'lon qilingan. Shuning uchun Docker anonim volume yaratgan edi. Konteyner o'chdi, anonim volume qoldi — lekin nomsiz, unga hech kim qaytib ulanmaydi.

Ikkala holat ham yaramaydi. Bizga shunday baza kerak: konteynerni o'chirib, PostgreSQL'ning yangi tuzatish versiyasi bilan qayta yaratsak ham, hamma jadval joyida qolsin.

Hayotiy o'xshatish: mehmonxona va uydagi seyf. Konteyner — mehmonxona xonasi: ketganingizdan keyin uni tozalab, boshqa mehmonga beradi. Xonada qoldirilgan narsa yo'qoladi. Volume — o'z seyfingiz: istalgan xonaga olib kirasiz, ketganda o'zingiz bilan olib chiqasiz. Xona almashadi, seyf ichidagi narsa — yo'q.

2. Uch usul

Docker konteynerga tashqi saqlash joyini uch usulda ulaydi. Sxemaga qarang — har usulda ma'lumot jismoniy jihatdan qayerda turadi:

flowchart LR
  V["Named volume: Docker hududi"] -->|"-v nom:/yol"| C["Konteyner"]
  B["Bind mount: sizning papkangiz"] -->|"-v papka:/yol"| C
  T["tmpfs: faqat RAM"] -->|"--tmpfs /yol"| C
Usul Ma'lumot qayerda Kim boshqaradi Qachon
Named volume Docker hududi (/var/lib/docker/volumes) Docker baza, doimiy ma'lumot
Bind mount host'dagi istalgan papka siz kod, sozlama, SQL fayllar
tmpfs operativ xotira kernel vaqtinchalik, maxfiy fayl

Uchala usulda ham konteyner ichida oddiy papka ko'rinadi. Konteyner ichidagi dastur farqni sezmaydi — Postgres o'z fayllarini qayerga yozayotganini bilmaydi. Farq faqat tashqarida.

3. Named volume: bazani saqlab qolish

3.1 Volume yaratish va ko'rish

Volume — Docker yaratadigan va boshqaradigan saqlash joyi. Uning nomi bor, konteynerdan alohida yashaydi.

bash
docker volume create kanon26-dars
docker volume inspect kanon26-dars

Natija:

text
kanon26-dars
[
    {
        "CreatedAt": "2026-10-24T03:02:18Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/kanon26-dars/_data",
        "Name": "kanon26-dars",
        "Options": null,
        "Scope": "local"
    }
]

Mountpoint — volume fayllari jismoniy turgan joy. Windows'da bu yo'l Windows Explorer'da yo'q: u Docker Desktop'ning WSL2 VM'i ichida. Driver: local — oddiy lokal disk. Boshqa driver'lar tarmoq diskiga yoki bulutga ham yoza oladi.

docker volume create ni yozish shart emas: docker run -v nom:/yol volume yo'q bo'lsa, uni o'zi yaratadi. Lekin aniq yaratish tushunarliroq.

3.2 Tajriba: konteyner o'chadi, ma'lumot qoladi

Volume'ni Postgres konteyneriga ulaymiz:

bash
docker run -d --name kanon26-v1 \
  -e POSTGRES_HOST_AUTH_METHOD=trust \
  -v kanon26-dars:/var/lib/postgresql \
  postgres:18

-v kanon26-dars:/var/lib/postgresql — "kanon26-dars volume'ini konteyner ichidagi /var/lib/postgresql papkasiga ula". POSTGRES_HOST_AUTH_METHOD=trust — parolsiz ulanish; faqat shu tajriba uchun, port ochilmagan.

Bazaga bitta jadval va bitta qator yozamiz:

bash
docker exec kanon26-v1 psql -U postgres -c \
  "create table eslatma(matn text);
  insert into eslatma values ('Volume ichida saqlanadi');"

Natija:

text
CREATE TABLE
INSERT 0 1

SQL buyruqlarini hali bilmaysiz — SQL tili va buyruq turlari darsida o'rganasiz. Qo'shtirnoq ichidagi yangi qator SQL uchun oddiy bo'shliq, ikki buyruq ; bilan ajralgan. Hozir ma'nosi yetarli: eslatma jadvali yaratildi va unga bitta matn yozildi.

Endi konteynerni butunlay o'chiramiz va xuddi shu volume bilan yangisini yaratamiz:

bash
docker rm -f kanon26-v1
docker run -d --name kanon26-v2 \
  -e POSTGRES_HOST_AUTH_METHOD=trust \
  -v kanon26-dars:/var/lib/postgresql \
  postgres:18
docker exec kanon26-v2 psql -U postgres -c "table eslatma;"

Natija (oxirgi buyruq):

text
          matn           
-------------------------
 Volume ichida saqlanadi
(1 row)

Yangi konteyner, eski ma'lumot. kanon26-v1 endi yo'q, lekin uning yozgani kanon26-v2 da turibdi. Ikkinchi konteyner ishga tushganda Postgres volume'da tayyor bazani ko'rdi va uni qaytadan yaratmadi.

Tekshirib ko'ring: Ikkinchi konteynerda -v ni unutsangiz, table eslatma; nima beradi?

Javob

Xato beradi — jadval yo'q. -v siz Docker yangi anonim volume yaratadi va Postgres u yerda bo'sh baza quradi. Eski ma'lumot kanon26-dars da xavfsiz turibdi, lekin yangi konteyner unga ulanmagan. Xato matni — ERROR: relation "eslatma" does not exist ("eslatma" jadvali mavjud emas; matnni o'z PostgreSQL 17.6 bazamizda tekshirdik). Bu xatoni SQL darslarida ko'p uchratasiz.

3.3 Volume ichida nima bor

Volume ulangan papkaga qaraymiz:

bash
docker exec kanon26-v2 \
  ls /var/lib/postgresql /var/lib/postgresql/18/docker

Ro'yxat uzun. Hozir faqat ikki narsani toping: ildizdagi 18 papkasi va ichkaridagi pg_wal hamda postgresql.conf.

text
/var/lib/postgresql:
18

/var/lib/postgresql/18/docker:
base
global
pg_commit_ts
pg_dynshmem
pg_hba.conf
pg_ident.conf
pg_logical
pg_multixact
pg_notify
pg_replslot
pg_serial
pg_snapshots
pg_stat
pg_stat_tmp
pg_subtrans
pg_tblspc
pg_twophase
PG_VERSION
pg_wal
pg_xact
postgresql.auto.conf
postgresql.conf
postmaster.opts
postmaster.pid

Volume ildizida bitta 18 papkasi — asosiy versiya raqami. Uning ichidagi docker papkasi — Postgres'ning ma'lumotlar katalogi (data directory): jadvallar (base), o'zgarishlar jurnali (pg_wal), sozlamalar (postgresql.conf, pg_hba.conf). Bu fayllarni qo'lda tahrirlamang. Ularning ma'nosini qismning keyingi darslarida birma-bir ochamiz.

4. PostgreSQL 18: volume yo'li o'zgardi

4.1 Eski yo'l bilan nima bo'ladi

Internetdagi qo'llanmalarning ko'pchiligi (va AI yordamchilarining javoblari) shunday yozadi: -v nom:/var/lib/postgresql/data. Bu 17 va undan oldingi image'lar uchun to'g'ri edi. 18 da sinab ko'ramiz:

bash
docker run --name kanon26-eski \
  -e POSTGRES_HOST_AUTH_METHOD=trust \
  -v kanon26-eski:/var/lib/postgresql/data \
  postgres:18

Natija uzun. Unda ikki alohida xabar bor: yulduzchalar orasidagi WARNING va undan keyingi Error. Ikkinchisi muhimroq.

text
********************************************************************************
WARNING: POSTGRES_HOST_AUTH_METHOD has been set to "trust". This will allow
         anyone with access to the Postgres port to access your database without
         a password, even if POSTGRES_PASSWORD is set. See PostgreSQL
         documentation about "trust":
         https://www.postgresql.org/docs/current/auth-trust.html
         In Docker's default configuration, this is effectively any other
         container on the same system.

         It is not recommended to use POSTGRES_HOST_AUTH_METHOD=trust. Replace
         it with "-e POSTGRES_PASSWORD=password" instead to set a password in
         "docker run".
********************************************************************************
Error: in 18+, these Docker images are configured to store database data in a
       format which is compatible with "pg_ctlcluster" (specifically, using
       major-version-specific directory names).  This better reflects how
       PostgreSQL itself works, and how upgrades are to be performed.

       See also https://github.com/docker-library/postgres/pull/1259

       Counter to that, there appears to be PostgreSQL data in:
         /var/lib/postgresql/data (unused mount/volume)

       This is usually the result of upgrading the Docker image without
       upgrading the underlying database using "pg_upgrade" (which requires both
       versions).

       The suggested container configuration for 18+ is to place a single mount
       at /var/lib/postgresql which will then place PostgreSQL data in a
       subdirectory, allowing usage of "pg_upgrade --link" without mount point
       boundary issues.

       See https://github.com/docker-library/postgres/issues/37 for a (long)
       discussion around this process, and suggestions for how to do so.

Ikki xabar chiqdi. Avval tarjima qilamiz.

Ogohlantirish (WARNING): "trust yoqilgan. Postgres portiga yeta oladigan har kim parolsiz kiradi — hatto parol berilgan bo'lsa ham. Docker'ning sukut sozlamasida bu — shu kompyuterdagi boshqa har qanday konteyner." Biz buni bilib qildik: tajriba, port ochilmagan.

Xato (Error): "18 va undan keyingi image'lar bazani versiya raqamli papkalarda saqlaydi. /var/lib/postgresql/data da esa ma'lumot bor ko'rinadi (ishlatilmagan volume). Odatda bu image yangilanib, baza pg_upgrade bilan yangilanmaganda bo'ladi. 18+ uchun tavsiya: bitta volume'ni /var/lib/postgresql ga ulang."

Konteyner exit kod 1 bilan to'xtadi — baza umuman ishga tushmadi. Image sizni "bazamni yo'qotdim" holatidan himoya qildi.

4.2 Nega shunday o'zgartirildi

Oldingi darsda docker image inspect da ikki maydon ko'rgan edik: VOLUME /var/lib/postgresql va PGDATA=/var/lib/postgresql/18/docker. Endi ma'nosi aniq:

  • Volume — bitta, /var/lib/postgresql da.
  • Baza — uning ichida 18/docker papkasida.

Keyinchalik 19-versiyaga o'tganda, xuddi shu volume ichida 19/docker paydo bo'ladi. Postgres'ning asosiy versiyalari orasida baza fayllari formati o'zgaradi, eski fayllarni yangi versiya to'g'ridan o'qiy olmaydi. Ko'chirish vositasi pg_upgrade ikkala papkani bitta disk ichida ko'rsa, tez ishlaydi. Image mualliflari shuning uchun yo'lni o'zgartirdi.

Diqqat: Eski qo'llanma yoki eski docker-compose.yml dan nusxa ko'chirsangiz, /var/lib/postgresql/data ni /var/lib/postgresql ga almashtiring. Bu kursda doim to'g'ri yo'lni ishlatamiz.

5. Volume zaxirasi

5.1 tar bilan nusxa

Volume — Docker hududida. Uni oddiy fayl sifatida nusxalash uchun kichik hiyla ishlatiladi: vaqtinchalik konteyner yaratamiz, unga ikki narsani ulaymiz — zaxiralanadigan volume va kompyuterdagi papka. Ichida esa tar bilan arxiv qilamiz. tar — fayllarni bitta arxivga yig'adigan Linux dasturi, czf — yaratish, gzip bilan siqish, fayl nomi.

bash
P=$(cygpath -w "$PWD/bind")
docker run --rm \
  -v kanon26-dars:/manba:ro \
  -v "$P:/zaxira" \
  postgres:18 tar czf /zaxira/kanon26-dars.tgz -C /manba .

Har qatorni o'qiymiz:

  • cygpath -w — Git Bash yo'lini Windows yo'liga (C:\...) aylantiradi. P — joriy papkadagi bind papkasining Windows yo'li.
  • -v kanon26-dars:/manba:ro — volume konteyner ichida /manba bo'ladi. :ro — read-only, faqat o'qish: zaxira olayotganda volume'ni tasodifan buzib qo'ymaymiz.
  • -v "$P:/zaxira" — kompyuterdagi papka konteyner ichida /zaxira bo'ladi. Bu — bind mount, uni keyingi bo'limda ochamiz.
  • postgres:18 tar ... — alohida image yuklamaslik uchun postgres:18 ning o'zidagi tar dan foydalandik.

Buyruq hech narsa chiqarmadi va exit kod 0 bilan tugadi. Arxiv bind papkasida paydo bo'ldi: 4 825 644 bayt, ya'ni ~4.8 MB (keyingi bo'limdagi ro'yxatda ko'rinadi). Bo'sh Postgres bazasi siqilgan holda shuncha joy oladi.

5.2 Halol eslatma: bu zaxira ishonchlimi?

Biz bu arxivni kanon26-v2 ishlab turganda oldik. Postgres shu paytda fayllarga yozayotgan bo'lishi mumkin edi. Ishlab turgan bazaning fayllarini nusxalash — yarim yozilgan sahifani ham nusxalash xavfi. Bunday arxivdan tiklangan baza ishga tushmasligi mumkin.

To'g'ri usullar:

  • Arxivdan oldin konteynerni to'xtating: docker stop, keyin tar, keyin docker start.
  • Yoki Postgres'ning o'z zaxira vositasi pg_dump bilan — u ishlab turgan bazadan ham izchil nusxa oladi. Uni Backup va restore darsida o'rganasiz.

Arxivdan tiklash teskari buyruq bilan bo'ladi: bo'sh yangi volume, vaqtinchalik konteyner va tar xzf (ochish). Tiklashni biz sinab ko'rmadik — shuning uchun bu yerda tayyor buyruq bermaymiz. Qoida: tiklab ko'rilmagan zaxira — zaxira emas.

6. Bind mount: kompyuterdagi papka

6.1 Faylni konteynerga berish

Bind mount — host'dagi mavjud papkani yoki faylni konteyner ichiga ulash. Volume'dan farqi: joyni siz tanlaysiz va fayllarni Windows'da oddiy dastur bilan ochasiz.

Bu kursda bind mount'ning eng foydali ishi — SQL fayllarni konteynerga berish. Bitta SQL faylni yaratamiz va konteyner ichidan ko'ramiz:

bash
echo "select 'bind mount orqali kelgan fayl' as xabar;" \
  > bind/salom.sql
P=$(cygpath -w "$PWD/bind")
docker run --rm -e POSTGRES_HOST_AUTH_METHOD=trust \
  -v "$P:/sql:ro" postgres:18 \
  sh -c 'ls -la /sql; id; stat -c "%U %a %n" /sql/salom.sql'

Natija:

text
total 4720
drwxrwxrwx 1 root root    4096 Oct 24 03:00 .
drwxr-xr-x 1 root root    4096 Oct 24 03:02 ..
-rw-r--r-- 1 root root 4825644 Oct 24 03:02 kanon26-dars.tgz
-rwxrwxrwx 1 root root      49 Oct 24 03:02 salom.sql
uid=0(root) gid=0(root) groups=0(root)
root 777 /sql/salom.sql

Konteyner ichida /sql papkasida ikkala fayl bor: Windows'da yaratilgan salom.sql va oldingi bo'limdagi zaxira arxivi. Ular nusxa emas — o'sha fayllarning o'zi. Windows'da salom.sql ni o'zgartirsangiz, konteyner yangi matnni darhol ko'radi.

id — konteyner ichidagi jarayon root (uid 0) nomidan ishlayotganini ko'rsatdi. stat -c "%U %a %n" — fayl egasi, ruxsat raqami va nomi.

6.2 Ruxsatlar muammosi

Fayl ruxsatlari darsida rwx, chmod 644 va fayl egasini o'rgangansiz. Endi natijaga diqqat bilan qarang:

  • Hamma fayl egasi — root root. Windows'da fayl egasi sizning foydalanuvchingiz edi.
  • salom.sql ruxsati — 777 (-rwxrwxrwx): hamma o'qiydi, yozadi va bajaradi.

Sabab: Windows'ning NTFS fayl tizimida Linux egalari va rwx ruxsatlari yo'q. Docker Desktop Windows papkasini Linux'ga uzatganda, ruxsatlarni "o'ylab topadi": egasi doim root, ruxsatlar keng. Konteyner ichida chmod yoki chown qilsangiz ham, Windows fayliga haqiqiy ruxsat yozilmaydi.

Bu nimaga ta'sir qiladi:

  • Ba'zi dasturlar o'z fayllarining ruxsatini tekshiradi. PostgreSQL ma'lumotlar katalogi uchun qat'iy ruxsat talab qiladi (faqat egasi kira olsin, 0700). Shuning uchun Postgres bazasini Windows papkasiga bind mount qilish muammoli. Biz buni sinamadik — baza uchun named volume ishlatamiz.
  • Linux server'da esa teskari muammo: konteyner ichidagi jarayon root dan boshqa foydalanuvchi (masalan uid 999) nomidan ishlasa, host papkasiga yozolmay Permission denied beradi. Bu deploy qismlarida uchraydi.
  • Docker hujjati Windows papkalarini konteynerga ulashni sekinroq deb ogohlantiradi va loyihalarni WSL2 fayl tizimida saqlashni tavsiya qiladi. Tezlikni biz o'lchamadik.

Tekshirib ko'ring: Nega zaxira olishda volume'ni :ro bilan, /zaxira papkasini esa :ro siz uladik?

Javob

Volume'dan faqat o'qiymiz — :ro uni tasodifiy o'zgarishdan himoya qiladi. /zaxira ga esa arxivni yozishimiz kerak — :ro bo'lsa, tar yoza olmasdi va Read-only file system xatosini berardi. Qoida: konteynerga faqat kerakli darajadagi huquqni bering.

6.3 Bind mount xavfi

Bind mount konteynerga host'ning haqiqiy fayllarini ochadi. Konteyner ichidagi jarayon root bo'lsa, ulangan papkadagi hamma narsani o'chira oladi. Shuning uchun:

  • Faqat kerakli papkani ulang — butun C:\Users yoki / ni emas.
  • O'qish yetarli bo'lsa — :ro.
  • Begona image'ga uy papkangizni ulamang: u yerda SSH kalitlar, brauzer ma'lumotlari, .env fayllar turadi.

7. tmpfs: faqat xotirada

tmpfs — operativ xotirada (RAM) yashaydigan vaqtinchalik fayl tizimi. Diskka hech narsa yozilmaydi. Konteyner to'xtashi bilan ichidagi hamma narsa yo'qoladi.

bash
docker run --rm --tmpfs /tmp/vaqtincha:size=16m postgres:18 \
  sh -c 'df -h /tmp/vaqtincha; echo salom > /tmp/vaqtincha/f;
  cat /tmp/vaqtincha/f'

Natija:

text
Filesystem      Size  Used Avail Use% Mounted on
tmpfs            16M     0   16M   0% /tmp/vaqtincha
salom

df -h — disk joyini ko'rsatadi. /tmp/vaqtincha — tmpfs, hajmi biz bergan 16 MB. Faylga salom yozildi va o'qildi. Konteyner tugadi — fayl ham yo'q.

Qachon kerak: juda tez vaqtinchalik fayllar, yoki diskka hech qachon tushmasligi kerak bo'lgan maxfiy ma'lumot. Postgres bazasini tmpfs'da saqlash testlarni tezlashtiradi — lekin baza har safar yo'qoladi. tmpfs faqat Linux konteynerlarida ishlaydi.

8. Volume'larni boshqarish va docker volume rm xavfi

8.1 Ro'yxat va o'chirish

bash
docker volume ls --filter name=kanon26
docker volume rm kanon26-dars
docker volume ls --filter name=kanon26

Natija:

text
DRIVER    VOLUME NAME
local     kanon26-dars
kanon26-dars
DRIVER    VOLUME NAME

Birinchi ro'yxatda kanon26-dars bor. docker volume rm uni o'chirdi va nomini qaytardi. Ikkinchi ro'yxat bo'sh.

8.2 Nega bu buyruq xavfli

E'tibor bering: Docker hech narsa so'ramadi. "Ishonchingiz komilmi?" degan savol, savat (korzina), "bekor qilish" — hech biri yo'q. eslatma jadvali, Volume ichida saqlanadi qatori, butun baza — bir buyruq bilan yo'q bo'ldi va qaytarib bo'lmaydi.

Faqat bitta himoya bor: volume'ni ishlatayotgan konteyner bo'lsa (hatto to'xtagan bo'lsa ham), Docker uni o'chirishga ruxsat bermaydi. Shuning uchun biz avval kanon26-v2 ni o'chirgan edik.

Yana xavfli buyruqlar:

  • docker volume prune — hech qaysi konteyner ishlatmayotgan volume'larni o'chiradi. To'xtatib, o'chirib qo'ygan konteyneringizning bazasi ham shu ro'yxatga tushadi.
  • docker rm -v — konteyner bilan birga uning anonim volume'larini o'chiradi (nomli volume'larga tegmaydi).
  • docker system prune --volumes — hamma ishlatilmayotgan narsani, volume'lar bilan birga.

Qoida: volume o'chirishdan oldin — nomini ikki marta o'qing, kerak bo'lsa zaxira oling. Server'da esa bu buyruqlarni faqat zaxira tekshirilgandan keyin.

Diqqat: "Disk to'lib qoldi" degan muammoni internetdagi maslahat bilan docker system prune -a --volumes orqali "hal qilish" — real kompaniyalarda baza yo'qotishning ma'lum sabablaridan biri. Avval docker system df bilan nima joy egallayotganini ko'ring.

9. SQL qadami: bu darsdan nima olamiz

Bu darsda loyihaga commit yo'q — faqat tajriba. Lekin uning natijasi keyingi darslarda to'g'ridan ishlatiladi. PostgreSQL o'rnatish va ulanish darsida vazifalar bazasining doimiy konteynerini yaratamiz. U shunday ulanadi:

  • named volume kanon26-data → /var/lib/postgresql (18 uchun to'g'ri yo'l);
  • port faqat 127.0.0.1 da;
  • SQL fayllar konteynerga beriladi va psql bilan bajariladi.

Shunda konteynerni istalgan paytda o'chirib qayta yaratish mumkin — bazangiz volume'da xavfsiz.

10. Ko'p uchraydigan xatolar

10.1 Eski volume yo'li

Error: in 18+, these Docker images are configured to store database data in a format which is compatible with "pg_ctlcluster" — yuqorida ko'rdik. Yechim: -v nom:/var/lib/postgresql.

10.2 -v ni unutish

Konteyner ishlaydi, baza bor, hammasi joyida. Bir kuni docker rm va qayta docker run — jadvallar yo'q. Ma'lumot anonim volume'da qolib ketgan. Yechim: doim nomli volume bering. Agar shunday bo'lib qolsa — docker volume ls da 64 belgili nomlarni qidiring, ma'lumot o'sha yerda bo'lishi mumkin. Shoshib prune qilmang.

10.3 Ishlab turgan bazadan nusxa

Fayllarni tar yoki oddiy nusxa bilan olish — baza ishlab turgan paytda buzilgan zaxira beradi. Yechim: to'xtatib nusxa yoki pg_dump.

10.4 Windows yo'llari Git Bash'da

Git Bash / bilan boshlanadigan argumentlarni ba'zan Windows yo'liga "o'zi aylantiradi". -v dagi yo'l kutilmagan joyga ulanadi. Yechim: host yo'lini cygpath -w bilan aniq Windows ko'rinishida bering (yuqoridagidek). Yoki bind mount buyruqlarini PowerShell'da yozing: -v "${PWD}\bind:/sql:ro".

11. Mashqlar

Mashqlar kurs/mashqlar/26/03-volume/ da.

1-mashq (oson): qaysi usul?

Har vaziyat uchun named volume, bind mount yoki tmpfs ni tanlang:

  1. Postgres bazasi — konteyner yangilansa ham saqlansin.
  2. Windows'da tahrirlayotgan sxema.sql faylingizni konteynerdagi psql ga berish.
  3. Testlar har safar toza bazada tez ishlasin, ma'lumot saqlanishi shart emas.
  4. Zaxira arxivini Windows papkangizga chiqarish.
Yechim
  1. Named volume — Docker boshqaradi, ruxsatlar to'g'ri, konteynerdan mustaqil.
  2. Bind mount (:ro bilan) — fayl Windows'da, konteyner uni darhol ko'radi.
  3. tmpfs — RAM'da, tez, konteyner bilan yo'qoladi.
  4. Bind mount — arxiv Windows'dagi papkaga tushishi kerak; zaxira volume'i esa :ro bilan ulanadi.

2-mashq (o'rta): ma'lumot saqlanganini isbotlang

Buyruqlarni yozing: mashq-data volume'i bilan pg-a konteynerini yarating, eslatma jadvaliga 'Birinchi konteyner' matnini yozing, pg-a ni o'chiring, xuddi shu volume bilan pg-b ni yarating va matnni o'qing. Oxirida hammasini tozalang.

Ishora: «Tajriba: konteyner o'chadi, ma'lumot qoladi» bo'limidagi buyruqlarni nomlarini almashtirib ishlating. -e POSTGRES_HOST_AUTH_METHOD=trust port ochilmagani uchun bu yerda mumkin.

Yechim
bash
docker run -d --name pg-a -e POSTGRES_HOST_AUTH_METHOD=trust \
  -v mashq-data:/var/lib/postgresql postgres:18
docker exec pg-a psql -U postgres -c \
  "create table eslatma(matn text);
  insert into eslatma values ('Birinchi konteyner');"
docker rm -f pg-a
docker run -d --name pg-b -e POSTGRES_HOST_AUTH_METHOD=trust \
  -v mashq-data:/var/lib/postgresql postgres:18
docker exec pg-b psql -U postgres -c "table eslatma;"
docker rm -f pg-b
docker volume rm mashq-data

pg-b dagi natija — Birinchi konteyner qatori (darsdagi kanon26-v2 chiqishi kabi). Agar pg-b dagi psql "connection refused" kabi xato bersa — Postgres hali ishga tushib ulgurmagan: bir-ikki soniya kutib qayta urining yoki docker logs pg-b da ready to accept connections ni kuting. Tozalash tartibi muhim: avval konteyner, keyin volume — aks holda Docker volume'ni "ishlatilmoqda" deb o'chirmaydi.

3-mashq (qiyin): to'g'ri docker run buyrug'ini yig'ish

Jamoangizda Postgres versiyasi har xil (16, 17, 18). postgresBuyrugi({ nom, volume, port, versiya }) funksiyasini yozing. U docker run uchun argumentlar massivini qaytarsin. Talablar:

  • volume yo'li: versiya 18 va undan katta — /var/lib/postgresql, kichik — /var/lib/postgresql/data;
  • port faqat 127.0.0.1 da;
  • port 1024–65535 oralig'ida bo'lmasa — RangeError tashlasin.

Natijani ["docker", ...args].join(" ") bilan chiqaring. Ishora: shart uchun ternar operator, xato uchun throw new RangeError(...) (throw va Error obyekti).

Yechim
js
function postgresBuyrugi({ nom, volume, port, versiya }) {
  if (!Number.isInteger(port) || port < 1024 || port > 65535) {
    throw new RangeError(`Port noto'g'ri: ${port}`);
  }
  const yol =
    versiya >= 18 ? "/var/lib/postgresql"
      : "/var/lib/postgresql/data";
  return [
    "run", "-d", "--name", nom,
    "-v", `${volume}:${yol}`,
    "-p", `127.0.0.1:${port}:5432`,
    `postgres:${versiya}`,
  ];
}

const yangi = postgresBuyrugi({
  nom: "pg18", volume: "pg18-data", port: 5499, versiya: 18,
});
console.log(["docker", ...yangi].join(" "));

const eski = postgresBuyrugi({
  nom: "pg16", volume: "pg16-data", port: 5416, versiya: 16,
});
console.log(["docker", ...eski].join(" "));

try {
  postgresBuyrugi({ nom: "x", volume: "x", port: 80, versiya: 18 });
} catch (e) {
  console.log(`${e.name}: ${e.message}`);
}

Konsolda:

text
docker run -d --name pg18 -v pg18-data:/var/lib/postgresql -p 127.0.0.1:5499:5432 postgres:18
docker run -d --name pg16 -v pg16-data:/var/lib/postgresql/data -p 127.0.0.1:5416:5432 postgres:16
RangeError: Port noto'g'ri: 80

Satr emas, massiv qaytarish — ataylab. Massivni child_process.spawn("docker", args) ga to'g'ridan berish mumkin: har argument alohida, shell ishtirok etmaydi. child_process darsidagi shell injection xavfi shu bilan yo'qoladi. 1024 dan kichik portlar Linux'da maxsus huquq talab qiladi — shuning uchun ular rad etildi.

4-mashq: SQL qadami — ishonchli zaxira

  1. mashq-data volume'i bilan Postgres konteyneri yarating va bitta jadval yozing (2-mashq).
  2. Konteynerni to'xtating (docker stop).
  3. «tar bilan nusxa» bo'limidagi usul bilan volume'ni zaxira.tgz ga arxivlang.
  4. Konteynerni qayta yoqing va jadval joyida ekanini tekshiring.
  5. Arxiv hajmini darsdagi 4.8 MB bilan solishtiring.
Yechim

2–4. docker stop pg-a → tar buyrug'i (-v mashq-data:/manba:ro) → docker start pg-a → docker exec pg-a psql -U postgres -c "table eslatma;". To'xtatilgan konteyner volume'ni "ushlab" turadi, lekin fayllarga yozmaydi — arxiv izchil bo'ladi.

  1. Bitta kichik jadvalli baza ham ~4–5 MB bo'ladi: hajmning asosiy qismi Postgres'ning tizim jadvallari va jurnal fayllari, sizning bitta qatoringiz emas. Raqam aniq mos kelmaydi — Postgres versiyasiga va jurnal holatiga bog'liq.

12. Real ishda

  • Har bir Postgres konteyneri — nomli volume bilan. Docker Compose fayllarida (33-qism) volumes: bo'limi aynan shu.
  • Dasturlashda bind mount: kod papkasini konteynerga ulab, o'zgarishni darhol ko'rish; SQL migratsiya fayllarini berish.
  • Zaxira: server'da volume arxivi yetarli emas — pg_dump, avtomatik jadval, boshqa serverga nusxa va tiklash mashqi kerak. Bu 27 va 34-qismlardagi mavzular.
  • Intervyu savollari: "Volume va bind mount farqi?", "Konteyner o'chirilganda ma'lumot qayerga ketadi?", "Postgres'ni Docker'da ishlatsangiz, ma'lumotni qanday saqlaysiz?". Yaxshi javob: "nomli volume, to'g'ri yo'l, va pg_dump bilan tekshirilgan zaxira".

Xulosa

  • Konteynerning yoziladigan qatlami konteyner bilan o'chadi — doimiy ma'lumot tashqarida bo'lishi kerak.
  • Named volume — Docker boshqaradi, baza uchun eng yaxshi; bind mount — sizning papkangiz, fayl berish uchun; tmpfs — faqat RAM.
  • PostgreSQL 18: -v nom:/var/lib/postgresql (baza 18/docker ichida); eski /data yo'li xato beradi.
  • Windows papkalari konteynerda root 777 bo'lib ko'rinadi — Linux ruxsatlari yo'q; baza uchun bind mount emas, volume.
  • Zaxira — to'xtatilgan konteynerdan yoki pg_dump bilan; tiklab ko'rilmagan zaxira — zaxira emas.
  • docker volume rm so'ramaydi va qaytarilmaydi; prune buyruqlari bilan ehtiyot bo'ling.

Keyingi dars: Nega ma'lumotlar bazasi — Docker tayyor; endi nega JSON fayl o'rniga baza kerakligini 10 ta parallel jarayon bilan o'lchab ko'ramiz.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Docker volume va bind mount: konteynerda ma'lumotni saqlash — IlmHamroh