20-bo‘lim

Amaliy loyiha - to'liq yetkazish

Dokon ilovasini noldan konteynerga joylash, test qilish, nashr etish, yetkazish, tekshirish va zaxiralash.

🕑 15 daqiqa o‘qish 📄 764 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Loyiha tuzilishi
  2. Ilova
  3. Dockerfile
  4. Testlar
  5. Obraz va nashr
  6. Skanerlash
  7. Yetkazish
  8. Yetkazishdan keyingi tekshiruv
  9. Tarmoq ajratish
  10. Ma'lumot saqlanishi
  11. Zaxira
  12. Toza to'xtash
  13. Yakuniy tekshiruv ro'yxati
  14. Bundan keyin nima?
  15. Xulosa

Yigirma bob davomida o'rgangan hamma narsani bitta loyihada yig'amiz: dokon ilovasini qurib, sinab, nashr etib, yetkazamiz va har bir qadamni tekshiramiz.

Loyiha tuzilishi #

Natija
loyiha/
├── compose.yaml
├── .dockerignore
└── ilova/
    ├── Dockerfile
    ├── boshla.sh      # ilova
    └── sinov.sh       # testlar

Ilova #

Ilova bazaga ulanadi, jadval yaratadi va soddagina HTTP javob beradi. Eng muhimi - SIGTERM ni ushlaydi (6-bob):

Natija
#!/bin/sh
trap 'echo "SIGTERM - toza toxtaymiz"; exit 0' TERM

echo "dokon: ishga tushdi, versiya ${DOKON_VERSIYA}"

psql "$BAZA_URL" -q -c "
  CREATE TABLE IF NOT EXISTS buyurtma (id serial PRIMARY KEY, nomi text);
  INSERT INTO buyurtma (nomi) SELECT 'Olma'
    WHERE NOT EXISTS (SELECT 1 FROM buyurtma);"

while true; do
  printf 'HTTP/1.1 200 OK\r\n\r\nOK\n' \
    | nc -l -p 8080 >/dev/null 2>&1 || sleep 1
done &
wait

Testlar oddiy, lekin haqiqiy tekshiruv qiladi:

Natija
#!/bin/sh
test -x /boshla.sh || { echo "TEST XATO: boshla.sh bajarilmaydi"; exit 1; }
grep -q 'trap' /boshla.sh \
    || { echo "TEST XATO: SIGTERM ishlovchisi yo'q"; exit 1; }
echo "TEST OK: barcha tekshiruv o'tdi"

Ikkinchi tekshiruv qiziq: u ilovada SIGTERM ishlovchisi borligini majburiy qiladi. Kimdir uni olib tashlasa, qurish yiqiladi.

Dockerfile #

DOCKERFILE
FROM alpine:3.21 AS asos
RUN apk add --no-cache postgresql-client netcat-openbsd \
    && adduser -D -u 10001 dokon
COPY --chmod=755 boshla.sh /boshla.sh
ENV DOKON_VERSIYA=1.0

FROM asos AS sinov
COPY --chmod=755 sinov.sh /sinov.sh
RUN /sinov.sh

FROM asos AS yakuniy
USER dokon
EXPOSE 8080
CMD ["/boshla.sh"]
QatorQaysi bobdan
--no-cache va bitta RUN5
Uch bosqich (asos, sinov, yakuniy)7, 17
COPY --chmod=75519
USER dokon15
CMD exec shaklda6

Testlar #

Terminal
docker build -q --target sinov -t dokon-sinov:1 ./ilova >/dev/null \
    && echo "testlar o'tdi"
Natija
testlar o'tdi

Obraz va nashr #

Terminal
docker images 127.0.0.1:5001/dokon/ilova:1.0 --format '{{.Size}}'
docker inspect 127.0.0.1:5001/dokon/ilova:1.0 \
    -f 'Foydalanuvchi: {{.Config.User}}'
Natija
20.1MB
Foydalanuvchi: dokon

20 megabayt - bazaga ulanadigan, HTTP javob beradigan to'liq ilova. Va u root sifatida ishlamaydi.

Skanerlash #

Terminal
docker run --rm -v /tmp/trivy-cache:/root/.cache aquasec/trivy:latest \
    image --quiet --severity CRITICAL --format json \
    127.0.0.1:5001/dokon/ilova:1.0 2>/dev/null \
    | grep -c '"VulnerabilityID"' || true
Natija
0

Kritik zaiflik yo'q. CI da bu qadam exit-code: "1" bilan ishlaydi - topilsa quvur to'xtaydi.

Yetkazish #

YAML
name: dokon

services:
  ilova:
    image: 127.0.0.1:5001/dokon/ilova:1.0
    environment:
      BAZA_URL: postgres://postgres:sinov@baza:5432/dokon
    depends_on:
      baza: { condition: service_healthy }
    networks: [old, orqa]
    restart: unless-stopped
    read_only: true
    tmpfs: [/tmp]
    cap_drop: [ALL]
    security_opt: [no-new-privileges:true]
    logging:
      driver: json-file
      options: { max-size: "10m", max-file: "3" }
    deploy:
      resources:
        limits: { cpus: "0.5", memory: 128M, pids: 100 }

  baza:
    image: postgres:17-alpine
    environment:
      POSTGRES_PASSWORD: sinov
      POSTGRES_DB: dokon
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d dokon"]
      interval: 2s
      retries: 20
    volumes: [dokon-ma:/var/lib/postgresql/data]
    networks: [orqa]
    restart: unless-stopped
    logging:
      driver: json-file
      options: { max-size: "10m", max-file: "3" }

networks:
  old:
  orqa:

volumes:
  dokon-ma:
Terminal
docker compose ps --format '{{.Service}} {{.State}}' | sort
docker compose logs ilova --no-log-prefix | head -2
Natija
baza running
ilova running
dokon: ishga tushdi, versiya 1.0
dokon: bazada 1 ta buyurtma

Ilova bazani topdi, jadval yaratdi va yozuvni qo'shdi.

Yetkazishdan keyingi tekshiruv #

Bu bo'lim - butun darslikning xulosasi. Har bir sozlama amalda ishlayotganini tasdiqlaymiz:

Terminal
for f in ReadonlyRootfs CapDrop PidsLimit Memory SecurityOpt; do
    printf '%-16s %s\n' "$f" \
        "$(docker inspect dokon-ilova-1 -f "{{.HostConfig.$f}}")"
done
docker inspect dokon-ilova-1 -f 'Foydalanuvchi    {{.Config.User}}'
Natija
ReadonlyRootfs   true
CapDrop          [ALL]
PidsLimit        100
Memory           134217728
SecurityOpt      [no-new-privileges:true]
Foydalanuvchi    dokon

Oltita qator, oltita himoya qatlami - va hammasi tekshirildi.

Dokon loyihasi - himoya qatlamlari Tarmoq ajratilgan - baza faqat orqa tarmoqda (9, 12-bob) Norut foydalanuvchi - USER dokon (15-bob) Faqat o'qish uchun fayl tizimi + tmpfs (14-bob) Barcha imkoniyatlar tashlangan - cap_drop ALL (15-bob) Resurs chegaralari - CPU, xotira, PID (14-bob) Jurnal aylanishi - disk to'lmaydi (13-bob) Salomatlik tekshiruvi + depends_on sharti (12-bob) Rootless Docker - konteyner root hostda oddiy foydalanuvchi (15-bob)
Har bir qatlam alohida bobdan - birga ishlaganda kuchli

Tarmoq ajratish #

Terminal
docker network inspect dokon_orqa \
    -f '{{range .Containers}}{{.Name}}
{{end}}' | sort | grep .
Natija
dokon-baza-1
dokon-ilova-1

Faqat ikki konteyner orqa tarmoqda. Boshqa hech kim bazaga yaqinlasha olmaydi.

Ma'lumot saqlanishi #

To'plamni butunlay 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 buyurtma'
Natija
1

Yozuv joyida - dokon-ma hajmi ma'lumotni saqlab qoldi.

Zaxira #

Terminal
docker run --rm -v dokon_dokon-ma:/ma -v /tmp/loyiha:/zaxira \
    alpine:3.21 tar czf /zaxira/dokon-ma.tar.gz -C /ma . 2>/dev/null
test -s /tmp/loyiha/dokon-ma.tar.gz && echo "zaxira yaratildi"
Natija
zaxira yaratildi
Bazani fayl sifatida zaxiralash - xavfli

Yuqoridagi usul umumiy hajmlar uchun to'g'ri: yuklangan rasmlar, hujjatlar.

Ishlayotgan baza uchun esa u xavfli - fayl nusxasi tranzaksiya o'rtasida olinishi mumkin. To'g'ri yo'l:

Natija
docker compose exec -T baza pg_dump -U postgres dokon \
    | gzip > zaxira/dokon-$(date +%F).sql.gz

Tiklashni ham sinab ko'ring - sinalmagan zaxira zaxira emas.

Toza to'xtash #

Eng oxirgi tekshiruv - ilova SIGTERM ni to'g'ri ushlaydimi:

Terminal
docker compose stop ilova >/dev/null 2>&1
docker inspect dokon-ilova-1 -f 'Chiqish kodi: {{.State.ExitCode}}'
Natija
Chiqish kodi: 0

Nol, 137 emas. Ilova signalni oldi, ishini tugatdi va o'zi chiqdi - 2-bobda boshlangan mavzu shu bilan yopiladi.

Yakuniy tekshiruv ro'yxati #

TekshiruvBobBuyruq
Aniq versiya tegi3docker inspect -f '{{.Config.Image}}'
Qatlam tartibi to'g'ri5docker build ikkinchi marta - CACHED
Qurish vositalari yo'q7docker run ... which gcc
Ma'lumot hajmda8docker volume ls
Baza porti chiqmagan9docker ps --format '{{.Ports}}'
Sir tarixda yo'q10docker history --no-trunc
Salomatlik tekshiruvi bor12.State.Health.Status
Jurnal aylanishi13.HostConfig.LogConfig
Resurs chegaralari14.HostConfig.Memory
Norut foydalanuvchi15.Config.User
Imkoniyatlar tashlangan15.HostConfig.CapDrop
Obraz skanerlangan15Trivy CI da
Toza to'xtash6.State.ExitCode = 0
Zaxira ishlaydi18Tiklashni sinang

Bundan keyin nima? #

Bu darslik bitta mashinadagi konteynerlar haqida edi. Keyingi qadamlar:

MavzuNima beradi
KubernetesKo'p serverga tarqatish, avtomatik tiklanish
Docker SwarmSoddaroq orkestrator, Compose sintaksisiga yaqin
Infratuzilma kod sifatidaTerraform, Ansible
KuzatuvPrometheus, Grafana, Loki
Xizmat to'riIstio, Linkerd - xizmatlar orasidagi TLS

Lekin ularning hammasi shu darslikdagi asoslarga tayanadi: obraz, qatlam, tarmoq, hajm, salomatlik tekshiruvi va signallar.

Eng muhim uchta odat
  1. O'lchang, taxmin qilmang. Bu darslikda ping ning CAP_NET_RAW siz ishlashi ham, shell shaklning sh ni PID 1 qilmasligi ham taxminga zid chiqdi.
  2. Tekshiring. Compose fayliga yozilgan sozlama amalda ishlashini docker inspect bilan tasdiqlang.
  3. Kichik saqlang. Kichik obraz tez yuklanadi, kam zaiflik olib keladi va tushunish osonroq.

Xulosa #

  • To'liq loyiha: uch bosqichli Dockerfile, testlar qurish ichida, registry ga nashr, Compose bilan yetkazish.
  • Test SIGTERM ishlovchisi borligini majburiy qiladi - kimdir uni olib tashlasa qurish yiqiladi.
  • Yakuniy obraz 20 MB va root sifatida ishlamaydi.
  • Yetkazishdan keyin oltita himoya sozlamasi docker inspect bilan tasdiqlandi.
  • Baza faqat orqa tarmoqda - tashqaridan ko'rinmaydi.
  • To'plam butunlay o'chirilib qayta ko'tarilganda ham ma'lumot saqlandi.
  • Umumiy hajmni tar bilan, bazani esa pg_dump bilan zaxiralang.
  • Sinalmagan zaxira - zaxira emas.
  • Toza to'xtash chiqish kodi 0 - 2-bobdagi 137 muammosi hal qilindi.
  • Keyingi qadam - orkestrator, lekin u ham shu asoslarga tayanadi.
Amaliy topshiriq
  1. Loyihani noldan yarating: Dockerfile, compose.yaml, .dockerignore.
  2. sinov bosqichiga o'z tekshiruvingizni qo'shing.
  3. Testni ataylab buzib, qurish to'xtashini ko'ring.
  4. Mahalliy registry ga nashr qiling.
  5. Trivy bilan skanerlang.
  6. compose up -d --wait bilan yetkazing.
  7. Oltita himoya sozlamasini docker inspect bilan tasdiqlang.
  8. Bazani pg_dump bilan zaxiralang va tiklang.
  9. compose stop dan keyin chiqish kodini tekshiring.
  10. Butun tekshiruv ro'yxatini skriptga aylantirib, CI ga qo'shing.

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.