17-bo‘lim

CI/CD bilan integratsiya

Testni qurish ichida bajarish, buildx quruvchilari, kesh va ko'p platformali obrazlar hamda GitHub Actions oqimi.

🕑 10 daqiqa o‘qish 📄 640 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Testni qurish ichida bajarish
  2. GitHub Actions oqimi
  3. Quruvchilar (builders)
  4. Yetkazish
  5. Qurish tezligi uchun amaliy qoidalar
  6. Xulosa

Konteynerning CI dagi asosiy foydasi shu: test ham, ishlab chiqarish ham bir xil muhitda ishlaydi.

Bu bobda testni qurish jarayonining ichiga joylashtiramiz va CI oqimini yig'amiz.

Testni qurish ichida bajarish #

7-bobdagi ko'p bosqichli qurish shu yerda ishlatiladi:

DOCKERFILE
FROM alpine:3.21 AS asos
COPY ilova.sh /ilova.sh
ENV DOKON_VERSIYA=1.0

FROM asos AS sinov
COPY sinov.sh /sinov.sh
RUN /sinov.sh

FROM asos AS yakuniy
CMD ["/ilova.sh"]

sinov bosqichi asos dan meros oladi va test skriptini qurish paytida ishga tushiradi.

Terminal
docker build -q --target sinov -t ci-sinov:1 . >/dev/null \
    && echo "test bosqichi o'tdi"
Natija
test bosqichi o'tdi

Endi eng muhimi. Testni ataylab buzamiz:

Terminal
sed -i 's/Dokon 1.0/Dokon 9.9/' sinov.sh
docker build --target sinov -t ci-sinov:2 . >/tmp/b.log 2>&1
echo "qurish chiqish kodi: $?"
grep -E 'TEST XATO|ERROR: process' /tmp/b.log | head -2 | fold -sw 74
Natija
qurish chiqish kodi: 1
#8 0.301 TEST XATO: Dokon 1.0
#8 ERROR: process "/bin/sh -c /sinov.sh" did not complete successfully:
exit code: 1

Qurish yiqildi. RUN nol bo'lmagan kod qaytarsa, obraz umuman yaratilmaydi.

Bu CI uchun juda qulay: alohida "test qadami" yozish shart emas, docker build ning o'zi yetarli.

Terminal
sed -i 's/Dokon 9.9/Dokon 1.0/' sinov.sh
docker build -q --target yakuniy -t ci-ilova:1.0 . >/dev/null
docker run --rm ci-ilova:1.0
Natija
Dokon 1.0

Yakuniy obrazda test skripti yo'q - u faqat sinov bosqichida qoldi.

Konteynerli CI quvuri Kommit git push Qurish + test --target sinov Skanerlash Trivy Push registry ga Yetkazish digest bilan Yiqilsa - quvur to'xtaydi, obraz yaratilmaydi Bitta artefakt butun quvur bo'ylab o'tadi Test qilingan obraz - aynan ishlab chiqarishga boradigan obraz. Qayta qurilmaydi.
Test qilingan obraz - aynan yetkaziladigan obraz

GitHub Actions oqimi #

YAML
name: Qurish va nashr

on:
  push:
    branches: [main]
    tags: ["v*"]

jobs:
  qurish:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Testlar
        uses: docker/build-push-action@v6
        with:
          target: sinov
          push: false
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Zaifliklarni skanerlash
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ghcr.io/${{ github.repository }}:sinov
          severity: CRITICAL,HIGH
          exit-code: "1"

      - name: Qurish va nashr
        id: nashr
        uses: docker/build-push-action@v6
        with:
          target: yakuniy
          push: true
          tags: |
            ghcr.io/${{ github.repository }}:sha-${{ github.sha }}
            ghcr.io/${{ github.repository }}:latest
          labels: |
            org.opencontainers.image.revision=${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Digestni chiqarish
        run: echo "Digest ${{ steps.nashr.outputs.digest }}"

Oxirgi qadam muhim: digest keyingi yetkazish bosqichiga uzatiladi - 16-bobdagi qoida bo'yicha.

CI keshi - qurishni bir necha barobar tezlashtiradi

cache-from: type=gha GitHub ning o'z keshini ishlatadi. Usiz har bir qurish noldan boshlanadi.

Boshqa variantlar:

TurQachon
type=ghaGitHub Actions
type=registry,ref=...Har qanday CI - kesh registry da
type=local,dest=...O'z serveringizdagi CI

5-bobdagi qatlam tartibi shu yerda qo'sh foyda beradi: to'g'ri tartib + CI keshi = bog'liqliklar deyarli hech qachon qayta o'rnatilmaydi.

Quruvchilar (builders) #

Terminal
docker buildx version
docker buildx ls --format '{{.Name}}' | head -2
Natija
github.com/docker/buildx v0.37.1 0b265a9f62db554fa9aba6dd19e1bd5704bc7d8a
default
default

Standart quruvchi - docker drayveri. U oddiy qurish uchun yetarli, lekin cheklovlari bor.

Standart drayver ko'p platformani jimgina bajarmaydi

Men shunday qurishni sinab ko'rdim:

Natija
docker buildx build --platform linux/amd64,linux/arm64 -t ci:kop --load .

Buyruq muvaffaqiyatli tugadi. Lekin natijani tekshirsak:

Natija
docker image inspect ci:kop -f '{{.Architecture}}'
amd64

Faqat bitta arxitektura. --load mahalliy saqlashga bitta obrazni yuklaydi va ko'p platformali ro'yxatni qo'llab quvvatlamaydi.

Haqiqiy ko'p platformali qurish uchun alohida quruvchi kerak:

Natija
docker buildx create --name kop --driver docker-container --use
docker buildx build --platform linux/amd64,linux/arm64 \
    -t reyestr/dokon:1.0 --push .

--load emas, --push: ko'p platformali obraz registry ga manifest ro'yxati sifatida boradi.

CI da docker/setup-buildx-action shu quruvchini o'zi yaratadi - shuning uchun u yerda muammo sezilmaydi.

Yetkazish #

Eng oddiy yetkazish - serverda compose pull va up:

YAML
name: Yetkazish

on:
  workflow_run:
    workflows: ["Qurish va nashr"]
    types: [completed]

jobs:
  yetkazish:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - name: Serverga ulanib yangilash
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /srv/dokon
            docker compose pull
            docker compose up -d --wait
            docker image prune -f

--wait (12-bobdan) bu yerda muhim: buyruq xizmatlar sog'lom bo'lguncha qaytmaydi, demak yetkazish natijasi haqiqiy bo'ladi.

CI sirlari - eng ko'p sizadigan joy

CI jurnallari ko'pincha ochiq bo'ladi. Shuning uchun:

  • Sirni hech qachon echo qilmang
  • --build-arg bilan uzatmang (10-bobda ko'rdik - tarixda qoladi)
  • CI ning o'z sirlar mexanizmidan foydalaning
  • Har bir omborxona uchun alohida token
  • Tokenga faqat kerakli huquq bering (packages: write)

GitHub Actions secrets.* qiymatlarini jurnalda avtomatik maskalaydi, lekin ular boshqa formatga o'tkazilsa (base64, JSON ichida) maskalash ishlamaydi.

Qurish tezligi uchun amaliy qoidalar #

QoidaTa'siri
Bog'liqliklarni alohida ko'chiring (5-bob)Eng katta foyda
CI keshini yoqing (type=gha)Qurishlar orasida saqlanadi
.dockerignore yozingKontekst kichrayadi
Ko'p bosqichli qurishYakuniy obraz kichik
Faqat kerakli platformani quringIkki barobar tez
Testni alohida bosqichdaParallel ishlatish mumkin

Xulosa #

  • RUN nol bo'lmagan kod qaytarsa, qurish yiqiladi - shuning uchun testni qurish ichiga joylash mumkin.
  • Buzilgan test bilan docker build chiqish kodi 1 qaytardi va obraz yaratilmadi.
  • Test skripti yakuniy obrazga tushmaydi - u alohida bosqichda qoladi.
  • CI da bitta artefakt butun quvur bo'ylab o'tadi: test qilingan obraz - aynan yetkaziladigan obraz.
  • CI keshi (type=gha, type=registry) qurishni sezilarli tezlashtiradi.
  • Standart docker drayveri --load bilan ko'p platformali obraz qura olmaydi - buyruq o'tadi, lekin natija bitta arxitektura bo'ladi.
  • Ko'p platforma uchun docker-container drayveri va --push kerak.
  • Yetkazishda compose up -d --wait ishlating - natija haqiqiy bo'ladi.
  • Sirni CI da hech qachon echo qilmang va --build-arg bilan uzatmang.
  • Nashr qadamining digestini keyingi bosqichga uzating.
Amaliy topshiriq
  1. Dockerfile ga sinov bosqichini qo'shing.
  2. Testni ataylab buzib, qurish chiqish kodini tekshiring.
  3. Yakuniy obrazda test fayllari yo'qligini tasdiqlang.
  4. docker buildx ls bilan quruvchilarni ko'ring.
  5. --platform linux/arm64 bilan qurib, Architecture ni tekshiring.
  6. docker-container drayveri bilan yangi quruvchi yarating.
  7. GitHub Actions oqimini yozing va testni qo'shing.
  8. Trivy qadamini exit-code: "1" bilan qo'shing.
  9. Kesh (type=gha) ni yoqib, ikkinchi qurish vaqtini o'lchang.
  10. Yetkazish oqimini --wait bilan yozing.

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.