Docker

Volume va tarmoq (network)

Konteynerlar vaqtinchalik (ephemeral) โ€” ularni o'chirsangiz, ichidagi ma'lumot ham yo'qoladi. Ma'lumotlar bazasi uchun bu falokat! Bu darsda ma'lumotni doimiy saqlash uchun volume'larni va konteynerlarni bir-biriga bog'lash uchun tarmoq (network)'ni o'rganamiz.

Muammo: konteyner ma'lumoti yo'qoladi

Konteyner ichida yozilgan har qanday ma'lumot konteynerning o'ziga tegishli. Konteynerni docker rm bilan o'chirsangiz โ€” u ma'lumot bilan birga butunlay yo'qoladi.

Buni tasavvur qiling: PostgreSQL konteynerida foydalanuvchilar bazasi bor. Konteynerni yangilash yoki qayta yaratish uchun o'chirdingiz โ€” va barcha foydalanuvchilar ma'lumoti ketdi. Bu qabul qilib bo'lmas holat.

Konteyner ichidagi fayl tizimi vaqtinchalik. Ma'lumotlar bazasi, yuklangan fayllar, foydalanuvchi kontenti kabi doimiy saqlanishi kerak bo'lgan narsalarni hech qachon shunchaki konteyner ichida qoldirmang.

Yechim: volume (hajm)

Volume โ€” bu Docker boshqaradigan, konteynerdan tashqarida saqlanadigan ma'lumot ombori. Konteynerni o'chirsangiz ham, volume va undagi ma'lumot saqlanib qoladi. Yangi konteyner o'sha volume'ga ulanib, avvalgi ma'lumotni davom ettira oladi.

Volume'ni konteynerga ulash uchun -v bayrog'i ishlatiladi:

docker run -d \
  --name baza \
  -e POSTGRES_PASSWORD=parol \
  -v baza-malumoti:/var/lib/postgresql/data \
  postgres:16

Bu yerda -v baza-malumoti:/var/lib/postgresql/data degani: baza-malumoti nomli volume'ni konteynerning /var/lib/postgresql/data papkasiga ula. PostgreSQL o'z ma'lumotini shu papkaga yozadi โ€” endi u volume'da, xavfsiz saqlanadi. Konteynerni o'chirib, qayta yaratsangiz ham ma'lumot joyida qoladi.

Volume va bind mount farqi

Ma'lumot saqlashning ikki asosiy usuli bor:

Farqni sintaksisdan bilish mumkin: agar chap tomonda oddiy nom bo'lsa โ€” bu volume; agar yo'l (/ bilan boshlanadi) bo'lsa โ€” bu bind mount:

# Nomli volume (Docker boshqaradi)
docker run -v mening-volumeim:/app/data ...

# Bind mount (kompyuterdagi aniq papka)
docker run -v /home/user/loyiha:/app ...

# Joriy papkani ulash ($(pwd) โ€” joriy papka yo'li)
docker run -v $(pwd):/app ...
Dasturlash paytida bind mount juda foydali: kompyuteringizda kodni o'zgartirasiz, u darhol konteynerda aks etadi โ€” image'ni qayta build qilish shart emas. Ishlab chiqarish (production) va ma'lumotlar bazalari uchun esa nomli volume afzal.

docker volume buyruqlari

Volume'larni boshqarish uchun quyidagi buyruqlar bor:

# Barcha volume'lar ro'yxati
docker volume ls

# Yangi volume yaratish
docker volume create mening-volumeim

# Volume haqida batafsil ma'lumot
docker volume inspect mening-volumeim

# Volume'ni o'chirish
docker volume rm mening-volumeim

# Ishlatilmayotgan barcha volume'larni tozalash
docker volume prune
docker volume rm va docker volume prune volume'dagi ma'lumotni butunlay o'chiradi va uni tiklab bo'lmaydi. Muhim ma'lumot volume'larini o'chirishdan oldin ikki marta tekshiring.

Muammo: konteynerlar bir-birini qanday topadi?

Endi tarmoqqa o'tamiz. Web-ilova konteyneri ma'lumotlar bazasi konteyneriga qanday ulanadi? Ular alohida, izolyatsiyalangan. IP manzillar esa konteyner har qayta ishga tushganda o'zgaradi โ€” shuning uchun IP'ga tayanish ishonchsiz.

Yechim โ€” konteynerlarni bitta tarmoq (network)ga ulash. Bir tarmoqdagi konteynerlar bir-birini nomi orqali topa oladi.

docker network โ€” tarmoq yaratish

Maxsus tarmoq yaratib, konteynerlarni unga ulaymiz:

# Yangi tarmoq yaratish
docker network create mening-tarmogim

# Barcha tarmoqlarni ko'rish
docker network ls

Endi ikkala konteynerni shu tarmoqqa ulab ishga tushiramiz. Bunda --network bayrog'i ishlatiladi:

# Ma'lumotlar bazasini tarmoqqa ulash
docker run -d \
  --name baza \
  --network mening-tarmogim \
  -e POSTGRES_PASSWORD=parol \
  postgres:16

# Web-ilovani o'sha tarmoqqa ulash
docker run -d \
  --name web \
  --network mening-tarmogim \
  -e DB_HOST=baza \
  -p 3000:3000 \
  mening-ilovam

Xizmat nomi orqali ulanish

Diqqat qiling: web-ilovaga DB_HOST=baza deb berdik โ€” bu ma'lumotlar bazasi konteynerining nomi. Bir tarmoqdagi konteynerlar bir-birini nomi orqali topa oladi.

Ya'ni web-ilova kodi ichida ma'lumotlar bazasiga baza:5432 manzili orqali ulanadi โ€” IP manzil kerak emas! Docker ichki DNS xizmati konteyner nomini avtomatik uning joriy IP manziliga tarjima qiladi.

// Node.js ilovada ma'lumotlar bazasiga ulanish (misol)
const pool = new Pool({
  host: 'baza',      // konteyner nomi โ€” IP emas!
  port: 5432,
  user: 'admin',
  password: 'parol',
  database: 'dukon'
});
Aynan shu mexanizmni oldingi darsda Docker Compose ichida ko'rgan edik. Compose barcha xizmatlarni avtomatik bir tarmoqqa ulaydi va ularni xizmat nomi orqali topish mumkin bo'ladi. Ya'ni Compose bu tarmoq ishini siz uchun avtomatik qiladi โ€” bu qulaylikning asosiy sababi.

Xulosa