12-bo‘lim
Ko'p xizmatli ilova
To'rt xizmatli haqiqiy to'plam - salomatlik tekshiruvi, depends_on sharti, tarmoq segmentatsiyasi va ma'lumot saqlanishi.
Ushbu bo‘lim mundarijasi
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 #
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:
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.
#!/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 #
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.
docker compose ps --format '{{.Service}} {{.State}}' | sort
baza running
ilova running
kesh running
veb running
Ilova nima qilganini ko'ramiz:
docker compose logs ilova --no-log-prefix
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:
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:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d dokon"]
interval: 2s
timeout: 3s
retries: 20
docker inspect dokon-baza-1 -f '{{.State.Health.Status}}'
healthy
condition | Nimani kutadi |
|---|---|
service_started | Konteyner ishga tushdi (standart) |
service_healthy | healthcheck muvaffaqiyatli o'tdi |
service_completed_successfully | Konteyner 0 kod bilan tugadi |
Uchinchisi migratsiya uchun: "avval migratsiya tugasin, keyin ilova boshlansin".
depends_on siz ham ilova ishlashi kerakShart 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:
docker network ls --filter name=dokon --format '{{.Name}}' | sort
dokon_old
dokon_orqa
Endi eng qiziq qismi. veb faqat old tarmoqda - u bazani
topa olmasligi kerak:
docker compose exec -T veb sh -c 'nslookup baza 2>&1 | tail -2' | head -1
** server can't find baza: NXDOMAIN
ilova esa ikkala tarmoqda:
docker compose exec -T ilova sh -c 'nslookup baza 2>&1 | grep -A1 "^Name:"'
Name: baza
Address: 172.20.0.2
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:
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'
2
Ikkita mahsulot joyida. Konteynerlar butunlay yangi, lekin
dokon-ma hajmi saqlanib qoldi.
Ilova ham buni ko'rdi:
docker compose logs ilova --no-log-prefix --tail 3
ilova: bazada 2 ta mahsulot
ilova: keshda holat = tayyor
ilova: tayyor
restart siyosati #
Har bir xizmatda restart: unless-stopped yozilgan:
| Qiymat | Qachon qayta ishga tushadi |
|---|---|
no | Hech qachon (standart) |
on-failure | Chiqish kodi 0 dan farqli bo'lsa |
on-failure:5 | Xuddi shunday, lekin 5 martagacha |
always | Har doim, hatto siz to'xtatsangiz ham |
unless-stopped | Har 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 #
docker compose down -v >/dev/null 2>&1
docker volume ls --filter name=dokon --format '{{.Name}}' | wc -l
0
Xulosa #
build:yozilsa, Compose obrazni o'zi quradi;image:yozilsa tayyorini oladi.- Xizmatlar bir-birini xizmat nomi bilan topadi - IP yozilmaydi.
depends_ono'zi yetarli emas: u faqat konteyner ishga tushishini kutadi, ichidagi dastur tayyorligini emas.condition: service_healthybilan birgahealthcheckyozilsa, kutish haqiqiy bo'ladi.service_completed_successfullymigratsiya kabi bir martalik vazifalar uchun.--waitbarcha xizmat sog'lom bo'lguncha kutadi - CI da juda foydali.- Ikki tarmoq:
vebbazani umuman ko'rmaydi (NXDOMAIN),ilovaesa 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.
- To'rt xizmatli
compose.yamlyozing vaup -d --waitqiling. docker compose psbilan barcha xizmat holatini ko'ring.healthcheckni olib tashlab, ilova yiqilishini kuzating.- Uni qaytarib,
service_healthysharti bilan sinang. - Yaratilgan tarmoqlarni ro'yxatlang.
vebdan bazaganslookupqilib, NXDOMAIN ni ko'ring.ilovadan o'sha so'rovni takrorlang.downvaupdan keyin ma'lumot qolganini tekshiring.restart: alwaysvaunless-stoppedfarqini sinab ko'ring.- Migratsiya xizmatini qo'shib,
service_completed_successfullybilan bog'lang.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.