Skip to content
Dokumentatsiya
Gitlab CI

Gitlab CI bilan CI/CD

Kirish

GitLab - bu veb-ga asoslangan Git repository manageri va DevOps platformasi bo'lib, u dastruchilar o'rtasidagi hamkorlikni soddalashtiradi. U GitLab CI orqali versiyani boshqarish(version control), code review, issue tracking va CI/CDni avtomatlashtirish kabi xususiyatlarni taklif etadi. GitLab CI bilan ishlab dasturchilar applicationlarni build qilish, testdan o'tkazish va deploymentni avtomatlashtirish uchun pipelinelarni belgilaydilar. Ushbu integratsiya jamoalarga yuqori sifatli dasturiy ta'minotni samarali va ishonchli yetkazib berish imkonini beradi.

Qisqa qilib aytganda Gitlab web-based git repository manager buni Githubga o'xshatish mumkin, Githubda hamma ishlagan bo'lishi kerak menimcha. Github asosan Open Source loyihalar uchundir private organizatsiylarda ham ishlash mumkin lekin Gitlabdek qulayliklar bo'lmaydi. Githubni o'z serverlaringizda o'rnatib,sozlab ishlata olmaysiz bu ba'zi bir tashkilotlar qonun-qoidalariga to'gri kelmaydi, ko'p tashkilotlar o'z loyiha kodlarini o'z serverlarida saqlashni xohlashdi bunda bizga Gitlab keladi. Siz Gitlabni o'zingizni serverlaringizda o'rnatib o'z Gitlab serveringizni sozlab be'malol ishlashingiz mumkin.

Gitlab CI bu Gitlabda loyihalarniga CI/CD pipelinelar yozish loyihalarni avtomatlashtirish bir nechta qulayliklarni beruvchi CI/CD tool hisoblanadi, Gitlab CIni Github Actionsga o'xshatish mumkin.

Bugungi amaliyotimizda biz Gitlab CI strukturarsini va qanday CI/CD yozishni ko'ramiz amaliyot qismida esa docker containerlar bilan ishlaydigan birinchi sodda CI/CD'ni Gitlab CI yordamida yozamiz, keyin uni optimizatsiya qilish va kengaytirish ustida ishlaymiz, keyin esa DEV, STAGE, PROD environmentlar sozlab shunga moslab Gitlab CI'da CI/CD'lar yozamiz va buni kengaytirib boramiz.

Ushbu amaliyotda biz global gitlab.com (opens in a new tab) dan foydalanamiz bu self-hosted deploy qilingan gitlab bilan deyarli bir xil agar siz o'zingizning serveringizga self-hosted Gitlab o'rnatmoqchi bo'lsangiz quyidagi qo'llanmani ko'rib chiqing - Gitlab Server o'rnatish va sozlash (opens in a new tab)

Boshlanishiga keling bir kichik amaliyotdan boshalaymiz. Birinchi navbatda bitta gitlab repositoriya yaratib olamiz. Create blank project tanlab repositoriya ochish bo'limiga o'tamiz.

Bu qismda repositoriyani nomini kiritib repositoriyani yaratib olamiz masalan gitlab-cicd-examples Repositoriyani xoxlagan IDE'yangizda yoki Gitlabning o'zining WEB IDEsi orqali ochib olishingiz mumkin masalan menga ko'proq WEB IDEA qulayroq. Repositoriyamizda .gitlab-ci.yml fayl ochib olib uni gitlabga push qilamiz.

.gitlab-ci.yml
stages:
  - build
  - test
  - deploy
 
build_job:
  stage: build
  script:
    - echo "Building the project"
test_job:
  stage: test
  script:
    - echo "Running tests"
 
deploy_job:
  stage: deploy
  script:
    - echo "Deploying the application"

gitlab-ci.yml config file ochib yuqoridagi yaml configni kiritib gitlabga push qilganizdan keyin sizda joblar ishlab turganini ko'rishingiz mumkin.

Joblarni ko'k ikonka ustiga bosib yoki jobs bo'limidan ko'rishingiz mumkin har bitta job ustiga bosib uning konsolini ochib jarayonlarni kuzatib borishingiz mumkin. Okey bizda barcha joblarimiz muvaffaqiyatli yakunlandi

Keling endi bu qanday ishlagani nimaligini ko'rib chiqamiz.

.gitlab-ci.yml — bu GitLab CI/CD uchun konfiguratsiya fayli bo'lib, pipeline'ning ish tartibini belgilaydi. Fayl YAML formatida yoziladi va uning tuzilishi aniq tartibga rioya qiladi. Pipeline — bu ketma-ket yoki parallel ravishda bajariladigan joblar to'plami. Har bir pipeline bosqichlardan iborat bo'lib, ular o'z navbatida job'ni o'z ichiga oladi.

.gitlab-ci.yml faylining asosiy printsipi

  • Bosqichlar (stages) bir-birining ketidan ishlaydi.
  • Job'lar qoidalar asosida bosqichlarda ishga tushadi.
  • Buyruqlar (script) bajarilib, natijalar logga yoziladi.
  • Artifacts va cache orqali natijalar yoki vaqtinchalik fayllar saqlanadi.
  • Qoidalar (rules) yordamida job qaysi holatda ishlashi aniqlanadi.

Bu struktura har qanday pipeline'ni samarali va moslashuvchan qilish imkonini beradi.

Struktura va asosiy elementlar

  1. stages

Pipeline'dagi bosqichlar(stages) ro'yxatini belgilaydi. Har bir job qaysi bosqichda bajarilishini shu yerda ko'rsatilgan tartibga qarab aniqlaydi.

Misol:

.gitlab-ci.yml
stages:
  - build
  - test
  - deploy

Bu holatda, build bosqichi birinchi, undan keyin test, keyin esa deploy bajariladi.

  1. default

Pipeline uchun default (standart) parametrlarni belgilaydi, masalan, image, before_script, yoki boshqa sozlamalar.

Misol:

.gitlab-ci.yml
stages:
  - build
  - test
 
default:
  image: python:3.9
  before_script:
    - pip install -r requirements.txt
 
build_job:
  stage: build
  script:
    - python setup.py build
 
test_job:
  stage: test
  script:
    - pytest tests/
  1. variables

Global o'zgaruvchilarni aniqlaydi. Bu o'zgaruvchilar barcha jobs'larda ishlatiladi.

Misol:

.gitlab-ci.yml
variables:
  ENVIRONMENT: production
  TIMEOUT: 30
  1. jobs Job'lar pipeline'ning asosiy qismini tashkil qiladi va ularning tuzilishi quyidagicha:
.gitlab-ci.yml
stages:
  - build
  - test
 
build_job:
  stage: build
  script:
    - npm install
    - npm run build
 
test_job:
  stage: test
  script:
    - npm run test

Job elementlari:

  • job_name: Jobning nomi. Bu foydalanuvchi tomonidan erkin belgilanadi.
  • stage: Job qaysi bosqichda bajarilishini belgilaydi. stages bo'limida aniqlangan bosqichlardan birini tanlash kerak.
  • script: Jobda bajariladigan buyruqlar ro'yxati. Bu buyruqlar ketma-ket bajariladi.
  • variables: Job uchun maxsus o'zgaruvchilar. Global o'zgaruvchilarni ustiga yozib yuborishi mumkin.
  • rules: Jobni bajarish qoidalarini belgilaydi (if, changes, when).
  • tags: Runner'larni filtrlash uchun ishlatiladi. Faqat belgilangan teglar mos keladigan Runner'larda ishga tushadi.
  • artifacts: Job natijalarini saqlaydi. Keyingi bosqichlarda foydalanish yoki yuklab olish uchun.
  • cache: Oraliq natijalarni saqlash va qayta foydalanishni tezlashtiradi.
  1. before_script va after_script

Job bajarilishidan oldin yoki keyin avtomatik ishlaydigan buyruqlarni belgilaydi.

Misol:

.gitlab-ci.yml
before_script:
  - echo "Setting up environment"
 
after_script:
  - echo "Cleaning up"

image - Joblar uchun Docker image belgilaydi. Agar pipeline Docker environmentda ishlasa, bu juda muhim. Agar jobni bajarish uchun maxsus muhit kerak bo'lsa, masalan, Python, Node.js yoki boshqa texnologiyalar uchun tayyor Docker image ishlatiladi.

.gitlab-ci.yml
stages:
  - test
 
test_job:
  stage: test
  image: python:3.9
  script:
    - pip install -r requirements.txt
    - pytest tests/

services - Job davomida qo'shimcha servicelar kerak bo'lsa, masalan, ma'lumotlar bazasi yoki kesh tizimi. Misol:

.gitlab-ci.yml
stages:
  - test
 
test_with_db:
  stage: test
  image: node:14
  services:
    - postgres:13
  variables:
    POSTGRES_DB: testdb
    POSTGRES_USER: user
    POSTGRES_PASSWORD: password
  script:
    - npm install
    - npm test

dependencies - Jobning oldingi job natijalaridan foydalanishini ta'minlaydi.

Misol:

.gitlab-ci.yml
stages:
  - build
  - test
 
build_job:
  stage: build
  script:
    - mkdir build
    - echo "build artifact" > build/artifact.txt
  artifacts:
    paths:
      - build/
 
test_job:
  stage: test
  script:
    - cat build/artifact.txt
  dependencies:
    - build_job

rules - Pipeline'ni optimallashtirish va faqat kerakli holatlarda jobni ishlatish uchun ishlatiladi. Jobni qachon va qaysi sharoitda bajarilishini belgilaydi.

Misol:

.gitlab-ci.yml
stages:
  - deploy
 
deploy_job:
  stage: deploy
  script:
    - echo "Deploying to production"
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: on_success
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: never

Pipeline Dizayni

Pipeline dizaynining asosiy maqsadi: jarayonlarni avtomatlashtirish, vaqtni optimallashtirish, va resurslardan samarali foydalanishni ta'minlash. Quyida stagelar, parallel joblar, triggerlar, va dependencylarni sozlash haqida ko'rib chiqamiz.

Bosqichlar (Stages) Pipeline bosqichlarga bo'linadi, bu jarayonlarni tartibga solishga yordam beradi. Har bir bosqich ma'lum bir vazifani bajaradi:

Masalan:

  • build: dastur kodini build qilish.
  • test: avtomatlashtirilgan testlarni bajarish.
  • deploy: dastur yoki serviceni deploy qilish.

Misol:

.gitlab-ci.yml
stages:
  - build
  - test
  - deploy
 
# Build bosqichi
maven_build:
  stage: build
  script:
    - echo "Building the project..."
    - mvn clean package
  artifacts:
    paths:
      - target/*.jar
    expire_in: 1 week
 
# Test bosqichi
unit_tests:
  stage: test
  script:
    - echo "Running unit tests..."
    - mvn test
 
integration_tests:
  stage: test
  script:
    - echo "Running integration tests..."
    - mvn verify
 
# Deploy bosqichi
deploy_to_production:
  stage: deploy
  script:
    - echo "Deploying to production..."
    - scp target/*.jar user@production:/opt/app/
    - ssh user@production "systemctl restart app.service"

Parallel Joblar Parallel joblar bir xil bosqichdagi vazifalarni bir vaqtning o'zida bajarishga imkon beradi. Bu katta hajmli jarayonlarni tezlashtirishga yordam beradi.

.gitlab-ci.yml
stages:
  - test
 
parallel_tests:
  stage: test
  parallel:
    matrix:
      - TEST_ENV: "linux"
      - TEST_ENV: "windows"
      - TEST_ENV: "macos"
  script:
    - echo "Testing in $TEST_ENV environment..."
    - npm test

Yuqorida Testlar Linux, Windows va MacOS muhitlarida bir vaqtning o'zida bajariladi.

Triggerlar Triggerlar pipeline jarayonlarini boshlash usullari:

  • Manual trigger: Qo'lda ishga tushiriladi, odatda keyingi bosqichni tekshirish yoki monitoring talab qilinganda ishlatiladi.
  • Scheduled trigger: Ma'lum vaqt oralig'ida avtomatik ishga tushiriladi (masalan, har kuni kechasi).
  • Triggered jobs: Bir job yoki boshqa pipeline tomonidan chaqiriladi.

Misol: Manual trigger

.gitlab-ci.yml
deploy_to_staging:
  stage: deploy
  script:
    - echo "Deploying to staging..."
    - scp app.jar user@staging:/opt/app/
  when: manual

Misol: Scheduled Trigger

.gitlab-ci.yml
nightly_build:
  stage: build
  script:
    - echo "Starting nightly build..."
    - mvn clean package
  only:
    - schedules

Dependency

Job'lar orasidagi bog'liqlikni sozlash uchun needs parametridan foydalaniladi.

Masalan bu konfiguratsiyada build_job tugaganidan keyin test_job va undan keyin esa deploy_job ishlashnini belgilaydi.

.gitlab-ci.yml
build_job:
  stage: build
  script:
    - echo "Building application..."
    - mvn clean package
 
test_job:
  stage: test
  script:
    - echo "Running tests..."
    - mvn test
  needs:
    - build_job
 
deploy_job:
  stage: deploy
  script:
    - echo "Deploying application..."
    - scp target/*.jar user@production:/opt/app/
    - ssh user@production "systemctl restart app.service"
  needs:
    - test_job

Yuqorida build_job dastlab ishga tushadi keyin test_job faqat build_job muvaffaqiyatli tugaganidan keyin boshlanadi, deploy_job esa testlar tugallangandan so'ng ishga tushadi.

Environment va secretlarni boshqarish

GitLab'da environment va secrets bilan ishlash, xavfsizlik va konfiguratsiya boshqaruvi uchun juda muhim. Quyida, ularni qanday boshqarish va ishlatish bo'yicha real-case misollar bilan tushuntirib beraman.

Environment Variablelar - bu pipeline davomida foydalaniladigan qiymatlar bo'lib, ular yashirin(protected) yoki umumiy bo'lishi mumkin.

GitLab'da o'zgaruvchilar ikki asosiy turga bo'linadi:

  • Protected Variablelar: Faqat protected branchlarda (masalan, main yoki production) uchun ishlaydi.
  • Umumiy Variablelar: Har qanday branch yoki environment uchun foydalaniladi.

GitLab'da secrets bilan ishlash maxfiy ma'lumotlarni boshqarish va ulardan xavfsiz foydalanishni ta'minlaydi. Secrets uchun bir nechta integratsiya usullari mavjud: Vault, Kubernetes Secrets, GitLab Secrets va boshqalar.

Secretlarni saqlashda Gitlab Secretsdan ko'ra Hashicorp Vault (opens in a new tab) tavsiya qilinadi!!!

Misol uchun Gitlab Secretsda ssh-keyni saqlab quyidagicha ishlatish mumkin.

-> Repositoriya -> Settings -> CI/CD -> Variables -> Add variable ga o'tib key va valueni yozib sqalab ishlata olamiz

Bu yerdan Add variable

Key va Valueni yozamiz

Keyin esa .gitlab-ci.yml da quyidagicha ishlatish mumkin.

.gitlab-ci.yml
stages:
  - deploy
 
deploy_job:
  stage: deploy
  script:
    - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - ssh -T git@example.com

CI/CD amaliyot Docker bilan

Amaliyotda uchun quyidagi repositoriyada kodlarni ishlatamiz gitlab.com/devops-journey (opens in a new tab) Gitlab CI namuna fayllarni ismoilovdevml/devops-tools (opens in a new tab)dan topishingiz mumkin.

CI/CD amaliyot quyidagicha ishlaydi faqat main branchga commit bo'lganda avtomatik ishga tushadi va loyihani build qilib Docker image yasaydi va uni Gitlab container registryga push qiladi va deploy bosqichida server ssh credentialslari bilan serverga kirib gitlab registrydan docker imageni pull qilib uni ishga tushiradi.

Birinchi navbatda kerakli variablelarni Gitlab CI/CD variablesga joylashimiz kerak bo'ladi, undan oldin esa serverga docker o'rnatib ssh sozlashimiz kerak bo'ladi.

Serverga Docker o'rnatish uchun quyidagi qo'llanmadan foydalanashingiz mumkin - Linux serverlarga Docker o'rnatish (opens in a new tab)

Biz yozgan CI/CD serverga ssh bilan krib ishlaydigan bosqichi bor shuning uchun serverimizda ssh key yaratib uni sozlab olishimiz kerak bo'ladi.

Serverga kirib sshkey generatsiya qilib olamiz. ssh-keygen buyrug'ini kiritib hammasiga ENTER bosib o'tamiz.

ssh-keygen

SSH directoriyaga kirib ko'ramiz, bizda id_rsa(private key) va id_rsa.pub public key va authorized_keys bo'lishi kerak agar authorized_key bo'lmasa yaratib olish kerak.

cd ~/.ssh/
ls

Public keyni(id_rsa.pub) authorized_keyga qo'shib qo'yamiz.

cat id_rsa.pub >> authorized_keys 

Private key(id_rsa) ni cat qilib ochib uni copy qilib olamiz uni Gitlab CI/CD variablega qo'shismiz kerak bo'ladi.

cat id_rsa

CI/CD ishlashi uchun kerak bo'lgan secretlarni Gitlab CI/CD variablega qo'shishimiz kerak bo'ladi.

-> Repositoriya -> Settings -> CI/CD -> Variables -> Add variable ga o'tib key va valueni saqlaymiz.

.gitlab-ci.yml dagi SSH_HOST variabelni qo'shamiz unga serverimiz IP sini berishim kerak bo'ladi.

SSH_USERga esa serverimizdagi userni kiritamiz uni quyidagi buyruq bilan aniqlash mumkin.

whoami

SSH_PRIVATE_KEYga id_rsa keyni qo'yamiz.

Bizda quyidagi CI/CD variablelar bo'lishi kerak

DevOps Journey loyihasi repositoriyasiga .gitlab-ci.yml fayl ochamiz va quyidagicha gitlab ci/cd yozamiz.

.gitlab-ci.yml
stages:
  - build_and_push
  - deploy
 
variables:
  IMAGE_NAME: devops-journey
  CONTAINER_NAME: devops-journey
  PORT: "3000:3000"
  REPO_NAME: $CI_PROJECT_PATH
  REGISTRY: "registry.gitlab.com"
 
build_and_push:
  stage: build_and_push
  image: docker:stable
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA .
    - docker push $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
 
deploy:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --update --no-cache openssh-client
  script:
    - mkdir -p ~/.ssh
    - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "echo "$CI_JOB_TOKEN" | docker login -u gitlab-ci-token --password-stdin $CI_REGISTRY"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker pull $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker stop $CONTAINER_NAME || true"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker rm $CONTAINER_NAME || true"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker run -d --name $CONTAINER_NAME -p $PORT $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA"
    
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

Bu konfiguratsiyani qo'shib main branchga push qilamiz.

Joblar bo'limga o'tsak joblar statusini ko'rishimiz mumkin.

Okey bizda Gitlab CI/CD muvaffaqiyatli ishladi.


Keling endi serverdan buni tekshirib ko'ramiz qani CI/CD to'gri ishlaganmikin ))

Okey serverda container chiki chiki ishlab turmoqda hammasi zo'r (rasm ustiga bosilganda kattalashadi)

Keling endi bu qandya ishlaganini tushuntirib beraman.

CI/CD 2ta stagedan iborat bo'lib bular build_and_push va deploy

build_and_push bu Docker imageni build qilib va uni Container registyrga pushg qilish vazifasini bajaradi.

deploy esa build_and_pushda build bo';gan imageni serverda ishga tushirib beradi.

.gitlab-ci.yml
stages:
  - build_and_push
  - deploy

Variables bo'limida quyidagi variablelar bor, bu global variablelar hisoblanadi.

.gitlab-ci.yml
variables:
  IMAGE_NAME: devops-journey
  CONTAINER_NAME: devops-journey
  PORT: "3000:3000"
  REPO_NAME: $CI_PROJECT_PATH
  REGISTRY: "registry.gitlab.com"
  • IMAGE_NAME Build qilingan Docker image nomi.
  • CONTAINER_NAME Docker konteyner nomi.
  • PORT Docker konteyner ichki va tashqi portini boglaydi (masalan, 3000 portni 3000 port bilan biriktiradi).
  • REPO_NAME Hozirgi GitLab loyihasining yo'li(path) (masalan, group/project).
  • REGISTRY Docker Registryning URL manzili.

Keling build_and_push stageni ko'rib chiqamiz.

.gitlab-ci.yml
build_and_push:
  stage: build_and_push
  image: docker:stable
  services:
    - docker:dind

Ushbu bosqichni bajarishda Docker CLI mavjud bo'lgan docker:stable docker imagedan foydalanilgan va services sifadida docker:dind Docker daemon (docker-in-docker) ishlatiladi.

.gitlab-ci.yml
before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

before_scriptda global variablelardan foydalagangan holda Container registryga login qilib kirish jarayoni yozilgan.

.gitlab-ci.yml
script:
  - docker build -t $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA .
  - docker push $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA

scriptda docker build buyruq yordamida docker image build qiladi va $CI_COMMIT_SHA unique key bilan teg qilib ikkinchi buyruqda variabledagi Container registryga imageni push qiladi.

.gitlab-ci.yml
rules:
  - if: '$CI_COMMIT_BRANCH == "main"'

Bu rules qismi esa qachon ishga tushishini bildiradi bu holda main branhchga commit bo'lganda build_and_push stage ishga tushadi.

Keling endi deploy stageni ko'rib chiqamiz.

.gitlab-ci.yml
deploy:
  stage: deploy
  image: alpine:latest

Bu qismda stage va undan qaysi imagedan foydalanish belgilangan bu holda eng yengil Linux distributivi alpine:latest docker image ishlatiladi.

.gitlab-ci.yml
before_script:
  - apk add --update --no-cache openssh-client

before_scriptda alpine:latest docker imagega ssh bilan ishlash uchun kerakli paketlar o'rnatiladi.

.gitlab-ci.yml
script:
  - mkdir -p ~/.ssh
  - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
  - chmod 600 ~/.ssh/id_rsa
  - ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts

script qismida Gitlab CI/CD variablesga qo'yilgan SSH_PRIVATE_KEY dan foydalanib ssh-keyni ulanish uchun solab kerakli permissionlarni beradi.

.gitlab-ci.yml
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "echo "$CI_JOB_TOKEN" | docker login -u gitlab-ci-token --password-stdin $CI_REGISTRY"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker pull $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker stop $CONTAINER_NAME || true"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker rm $CONTAINER_NAME || true"
    - ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST "docker run -d --name $CONTAINER_NAME -p $PORT $REGISTRY/$REPO_NAME/$IMAGE_NAME:$CI_COMMIT_SHA"

Yuqoridagi buyruqlar ssh bilan serverga kirib quyidagi ketma ketlikda ishga tushadi, birinchi bo'lib docker login qilib Container Registryga authentikatsiya qilib kiradi keyin esa docker pull bilan build_and_push stageda build bo'lgan va unique tag qilingan docker imageni pull qilib oladi va shu nom bilan ishlab turgan docker imageni to'xtatib/o'chirib yangi docker pull qilib olgan docker imageni global variableda berilgan port container nomi va aniq belgilangan imageni ishga tushiradi, qarabsiznki sizning applicationchangiz ishlab turibdi :)

.gitlab-ci.yml
rules:
  - if: '$CI_COMMIT_BRANCH == "main"'

Bu rules esa qachon deploy job ishga tushishini bildiradi bu holdat main branchga push bo'lganida avtomatik ishlaydi.

Vazifa: Endi esa qizga qiziq bir vazifa beraman :)

Vazifa shundan iboratki shu pipelinedan foydalanib endi siz muliple environment uchun Gitlab CI/CD yozishingiz kerak bo'ladi. Kichik yordam: main(production), dev(development), stage(staging) branchlar qiling va bitta umumiy .gitlab-ci.yml yozinng va branchlarga rule yozib chiqing masalan main branchda o'zgarish bo'lganda production serverlarga main branchdagi kodlarni ishga tushirsin va buyo'gi o'zingizning fantaziyangizga bo'gliq :)

Qo'shimcha