12-bo‘lim

Ko'p xizmatli ilova

To'rt xizmatli haqiqiy to'plam - salomatlik tekshiruvi, depends_on sharti, tarmoq segmentatsiyasi va ma'lumot saqlanishi.

🕑 14 daqiqa o‘qish 📄 640 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. To'plam tuzilishi
  2. Xizmatni Dockerfile dan qurish
  3. Ishga tushirish
  4. Salomatlik tekshiruvi va depends_on
  5. Tarmoq segmentatsiyasi
  6. Ma'lumot saqlanadimi?
  7. restart siyosati
  8. Tozalash
  9. Xulosa

Oldingi bobda ikkita oddiy xizmatni ko'rdik. Endi haqiqiy tuzilmani quramiz: veb server, ilova, baza va kesh.

Bu bobda uchta yangi narsa bor: salomatlik tekshiruvi, tarmoq segmentatsiyasi va xizmatni Dockerfile dan qurish.

To'plam tuzilishi #

Ikki tarmoqli to'plam dokon_old veb nginx:alpine 8099 -> 80 ilova build: ./ilova ikkala tarmoqda dokon_orqa baza postgres:17-alpine hajm: dokon-ma kesh redis:7-alpine port chiqmaydi veb orqa tarmoqda YO'Q - u bazani umuman ko'rmaydi. ilova ikkala tarmoqda - u ko'prik vazifasini bajaradi.
Ikki tarmoq - veb buzilsa ham baza unga ochiq emas
YAML
name: dokon

services:
  veb:
    image: nginx:alpine
    ports:
      - "8099:80"
    networks: [old]
    restart: unless-stopped

  ilova:
    build: ./ilova
    environment:
      BAZA_URL: postgres://postgres:sinov@baza:5432/dokon
    depends_on:
      baza:
        condition: service_healthy
      kesh:
        condition: service_started
    networks: [old, orqa]
    restart: unless-stopped

  baza:
    image: postgres:17-alpine
    environment:
      POSTGRES_PASSWORD: sinov
      POSTGRES_DB: dokon
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d dokon"]
      interval: 2s
      timeout: 3s
      retries: 20
    volumes:
      - dokon-ma:/var/lib/postgresql/data
    networks: [orqa]
    restart: unless-stopped

  kesh:
    image: redis:7-alpine
    networks: [orqa]
    restart: unless-stopped

networks:
  old:
  orqa:

volumes:
  dokon-ma:

Xizmatni Dockerfile dan qurish #

ilova xizmatida image: emas, build: yozilgan - Compose obrazni o'zi quradi:

DOCKERFILE
FROM alpine:3.21
RUN apk add --no-cache postgresql-client redis
COPY boshla.sh /boshla.sh
CMD ["/boshla.sh"]

Ilova ishi oddiy: bazaga jadval yaratadi, keshga kalit yozadi va natijani chop etadi.

Natija
#!/bin/sh
set -e

psql "$BAZA_URL" -q -c "
  CREATE TABLE IF NOT EXISTS mahsulot (id int PRIMARY KEY, nomi text);
  INSERT INTO mahsulot VALUES (1, 'Olma'), (2, 'Anor')
    ON CONFLICT (id) DO NOTHING;"

redis-cli -h kesh SET dokon:holat tayyor > /dev/null
echo "ilova: keshda holat = $(redis-cli -h kesh GET dokon:holat)"

E'tibor bering: baza va kesh - bu xizmat nomlari. Ilova ularni IP orqali emas, nom orqali topadi.

Ishga tushirish #

Natija
docker compose up -d --wait

--wait muhim: u barcha xizmat sog'lom bo'lguncha kutadi va shundan keyingina qaytadi. Mening kompyuterimda bu birinchi safar (obraz qurish bilan birga) 28 soniya davom etdi.

Terminal
docker compose ps --format '{{.Service}} {{.State}}' | sort
Natija
baza running
ilova running
kesh running
veb running

Ilova nima qilganini ko'ramiz:

Terminal
docker compose logs ilova --no-log-prefix
Natija
ilova: baza va keshni tekshiramiz
ilova: bazada 2 ta mahsulot
ilova: keshda holat = tayyor
ilova: tayyor

Baza ham, kesh ham javob berdi.

Salomatlik tekshiruvi va depends_on #

Bu to'plamdagi eng muhim tafsilot:

YAML
depends_on:
  baza:
    condition: service_healthy

depends_on o'zi yetarli emas. U faqat konteyner ishga tushishini kutadi - ichidagi dastur tayyor bo'lishini emas.

PostgreSQL konteyneri bir zumda ishga tushadi, lekin ulanishni qabul qilishga bir necha soniya keyin tayyor bo'ladi. Shart qo'shilmasa, ilova erta boshlanadi va ulana olmay yiqiladi.

service_healthy sharti esa healthcheck natijasini kutadi:

YAML
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U postgres -d dokon"]
  interval: 2s
  timeout: 3s
  retries: 20
Terminal
docker inspect dokon-baza-1 -f '{{.State.Health.Status}}'
Natija
healthy
conditionNimani kutadi
service_startedKonteyner ishga tushdi (standart)
service_healthyhealthcheck muvaffaqiyatli o'tdi
service_completed_successfullyKonteyner 0 kod bilan tugadi

Uchinchisi migratsiya uchun: "avval migratsiya tugasin, keyin ilova boshlansin".

depends_on siz ham ilova ishlashi kerak

Shart qo'shsangiz ham, xizmat ishlash paytida uzilishi mumkin - baza qayta ishga tushadi, tarmoq bir soniya yo'qoladi.

Shuning uchun ilova ulanishni qayta urinish bilan qilishi kerak: 1 soniya, 2, 4, 8 - shunday kechikish bilan.

depends_on faqat ishga tushish tartibini hal qiladi, ishonchlilikni emas.

Tarmoq segmentatsiyasi #

Compose ikkita tarmoq yaratdi:

Terminal
docker network ls --filter name=dokon --format '{{.Name}}' | sort
Natija
dokon_old
dokon_orqa

Endi eng qiziq qismi. veb faqat old tarmoqda - u bazani topa olmasligi kerak:

Terminal
docker compose exec -T veb sh -c 'nslookup baza 2>&1 | tail -2' | head -1
Natija
** server can't find baza: NXDOMAIN

ilova esa ikkala tarmoqda:

Terminal
docker compose exec -T ilova sh -c 'nslookup baza 2>&1 | grep -A1 "^Name:"'
Natija
Name:    baza
Address: 172.20.0.2
Nima uchun bu muhim

Veb server - internetga ochiq qism, demak u eng ko'p hujumga uchraydi.

U buzilgan taqdirda ham hujumchi bazaga to'g'ridan-to'g'ri ulana olmasligi kerak. Ikki tarmoq aynan shuni beradi.

Bu 6-bobdagi "tarmoq segmentatsiyasi" g'oyasining konteyner darajasidagi ko'rinishi.

Ma'lumot saqlanadimi? #

Butun to'plamni o'chirib, qaytadan ko'taramiz:

Terminal
docker compose down >/dev/null 2>&1
docker compose up -d --wait >/dev/null 2>&1
sleep 2
docker compose exec -T baza psql -U postgres -d dokon -t -A -c \
    'SELECT count(*) FROM mahsulot'
Natija
2

Ikkita mahsulot joyida. Konteynerlar butunlay yangi, lekin dokon-ma hajmi saqlanib qoldi.

Ilova ham buni ko'rdi:

Terminal
docker compose logs ilova --no-log-prefix --tail 3
Natija
ilova: bazada 2 ta mahsulot
ilova: keshda holat = tayyor
ilova: tayyor

restart siyosati #

Har bir xizmatda restart: unless-stopped yozilgan:

QiymatQachon qayta ishga tushadi
noHech qachon (standart)
on-failureChiqish kodi 0 dan farqli bo'lsa
on-failure:5Xuddi shunday, lekin 5 martagacha
alwaysHar doim, hatto siz to'xtatsangiz ham
unless-stoppedHar doim, lekin siz to'xtatgan bo'lsangiz - yo'q

unless-stopped odatda eng to'g'ri tanlov: server qayta yuklansa xizmat ko'tariladi, lekin siz ataylab to'xtatgan konteyner to'xtaganicha qoladi.

Tozalash #

Terminal
docker compose down -v >/dev/null 2>&1
docker volume ls --filter name=dokon --format '{{.Name}}' | wc -l
Natija
0

Xulosa #

  • build: yozilsa, Compose obrazni o'zi quradi; image: yozilsa tayyorini oladi.
  • Xizmatlar bir-birini xizmat nomi bilan topadi - IP yozilmaydi.
  • depends_on o'zi yetarli emas: u faqat konteyner ishga tushishini kutadi, ichidagi dastur tayyorligini emas.
  • condition: service_healthy bilan birga healthcheck yozilsa, kutish haqiqiy bo'ladi.
  • service_completed_successfully migratsiya kabi bir martalik vazifalar uchun.
  • --wait barcha xizmat sog'lom bo'lguncha kutadi - CI da juda foydali.
  • Ikki tarmoq: veb bazani umuman ko'rmaydi (NXDOMAIN), ilova esa ikkalasida.
  • Bu ochiq qism buzilganda ham bazani himoya qiladi.
  • Nomlangan hajm butun to'plam o'chirilib qayta ko'tarilganda ham ma'lumotni saqlaydi.
  • restart: unless-stopped - ko'p holat uchun to'g'ri tanlov.
Amaliy topshiriq
  1. To'rt xizmatli compose.yaml yozing va up -d --wait qiling.
  2. docker compose ps bilan barcha xizmat holatini ko'ring.
  3. healthcheck ni olib tashlab, ilova yiqilishini kuzating.
  4. Uni qaytarib, service_healthy sharti bilan sinang.
  5. Yaratilgan tarmoqlarni ro'yxatlang.
  6. veb dan bazaga nslookup qilib, NXDOMAIN ni ko'ring.
  7. ilova dan o'sha so'rovni takrorlang.
  8. down va up dan keyin ma'lumot qolganini tekshiring.
  9. restart: always va unless-stopped farqini sinab ko'ring.
  10. Migratsiya xizmatini qo'shib, service_completed_successfully bilan bog'lang.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.