Koddan Servergacha: Jenkins bilan Docker CI/CD va Discord bilan integratsiya
Kirish
Jenkins - bu doimiy Continuous Integration/Continuous Deployment (CI/CD) pipelinei uchun ajoyib tool, ayniqsa Docker konteynerlari bilan ishlashda.
Jenkins CI/CD jarayonini osonlashtiradigan open-source avtomatlashtirish serveri bo'lib, ishlab chiquvchilarga applicationlarni build qilish, testdan o'tkazish va deploymentni avtomatlashtirish imkonini beradi. Docker bilan birlashganda, u konteynerlashtirilgan workflowlari uchun kuchli yechim taklif qiladi, bu turli muhitlarda izchillik(consistency) va portativlikni ta'minlaydi.
Jenkins Docker bilan birgalikda izchil va samarali development workflowni yaratish uchun konteynerlashtirishdan foydalangan holda CI/CD jarayonini soddalashtiradi. Jenkins pipelinelarida Docker imkoniyatlaridan foydalanish orqali jamoalar dasturiy ta'minotni tezroq va ishonchli yetkazib berishga erishishlari mumkin.
Bugun ushbu qo'llanmamizda konteynerlashtirilgan ilovalarni Jenkins orqali CI/CD avtomatizatsiya qilamiz.
Ushbu jarayon quyidagicha bosqichlarsan iborat bo'ladi. (qisqa tushuntirish)
-
CI CI qismida biz loyiha source kodlari joylashgan github yoki gitlab bilan ishlaymiz. Github yoki Gitlabda yangi kod qo'shilsa Jenkins CI pipeline avtomatik ishga tushadigan qilamiz. Keyingi qismida o'zgarish bo'lganinidan keyin Github yoki Gitlabdan loyiha repositoriyasi va belgilangan branchdan loyiha source kodlarini runner yuklab oladi. Loyiha source kodlari yuklab olinganidan keyin test uchun Docker image build qilinadi, agara Docker image build bo'lsa keyingi bosqichda CD o'tadi aks holda shu joyida jarayon to'xtaydi. Docker image muvaffaqiyatli build bo'lganidan keyin birorta Docker Registryga push qilinadi. Shu jarayonlar hammasi bajarilganida CI bosqichimiz tugab CD bosqichiga o'tiladi.
-
CD CI qismida applicationimiz testlardan o'tib Docker image build qilinib Docker Registyga push qilingan bo'ladi. CD qismida ssh orqali serverga kirib bundan oldingi docker containerni to'xtatib, o'chirib yangi docker imageni Docker Registydan pull qilib olib uni Docker container qilib ishga tushirib qo'yishimiz kerak.
-
Notification Agar CI/CD jarayoni muvaffaqiyatli yoki muvaffaqiyatsiz bo'lsa Discord serverga notification yuboradigan qilib Discord bilan integratsiya qilamiz.
Ishni boshlash
Ushbu amaliyotni amalga oshirish uchun bizga quyidagi minimum server talablaridagi server kerak bo'ladi.
Minimum Server talabi
OS | RAM | CPU | Xotira | Static IP |
---|---|---|---|---|
Ubuntu 20.04 | 8GB | 4vCPU 2 core | 50GB | Ha kerak |
Tavsiya qilinadigan mimimum server talabi
OS | RAM | CPU | Xotira | Static IP | Server nomi |
---|---|---|---|---|---|
Ubuntu 20.04 | 12GB | 8vCPU 4 core | 50GB | Ha kerak | Jenkins Server |
Ubuntu 20.04 | 8GB | 4vCPU 2 core | 50GB | Ha kerak | Application Server |
Ushbu amaliyotda biz Jenkins, Docker, Container Registry (Dockerhub va GCR(Google Container Registry)), Github yoki Gitlab, Discord va Ubuntu server ishlatamiz
ESLATMA-> Ushbu amaliyotda biz devops-journey (opens in a new tab) platformasi manba kodlaridan foydalanamiz. Stars(yulduzcha) bosib qo'yish esdan chiqmasin :)
Jenkins o'rnatish
Amaliyotning birinchi qadami bu Serverga Jenkins o'rnatishdan boshlanadi. Bundan oldingi qo'llanmalarda Jenkins o'rnatish haqida yozilgan. Linux Serverlarga Jenkins o'rnatish (opens in a new tab) qo'llanmasidan foydalanib serveringizga jenkins o'rnatib olishingiz mumkin. Serveringizga Jenkins o'rnatib boshlang'ich sozlab olganingizdan keyin keyingi bosqichga o'tsak bo'ladi.
Docker o'rnatish
Biz ilovamizni Docker containerlarda ishga tushiramiz shuning uchun serverimizga Docker o'rnatib olishimiz kerak bo'ladi. Linux serverlarga Docker o'rnatish (opens in a new tab) qo'llanasidan foydalanib serveringizga Docker o'rnatib oling.
Git bilan ishlash
Applicationlarimiz kodlarini birorta VCS(Version Control System)da saqlanadi ushbu amaliyotda Github va Gitlab bilan ishlaydigan Jenkins CI pipeline yozamiz. Gitdan private repositoriyalarni klon qilib olish uchun ushbu repositoriyalarga ruxsati bor userlardan Personal access token tokenlar olinadi va Jenkins credendialsga qo'shib qo'yiladi. Bundan maqsad Jenkins pipeline ushbu Personal access token orqali Github yoki Gitlabdan private repositoriyalarni clon qila olishi va ishlata olishidir.
ESLATMA-> Ko'p startuplar kichik jamolar Github ishlatishadi, boshqalar esa enterprise Gitlabni o'z serverlarda ishga tushirib ishlatishadi. Bu amaliyotda ikkalasi bilan ham ishlash yozilgan. Sizning jamoyingiz qaysi birini ishlatsa shunga mosini qo'llaysiz.
Personal access token olish
Github uchun
Github profilingizga kirib Settings sozlamalar bo'limga kiring.
Keyin Developer settings bo'limga kiring.
Personal access tokens -> Tokens(classic)
->Generate new token(classic)
Personal access tokenga nom berib va ishlash mudatini belgilab admin accesslarni beramiz va Generate token bosib token generatsiya qilib olamiz.
Sizga Github Personal access token generatsiya qilib berganida uni nusxalab olib qo'yishingiz kerak bo'ladi. Bu Personal access tokenni Jenkinsda credentialsga qo'shib qo'yib Jenkins pipelineda ishlatamiz.
Gitlab uchun
Gitlab profilingizga kirib Pereferences bo'limga kirib Accsess Tokensga o'tamiz.
Accsess Tokensga kirganimizdan keyin Token nomi ishlash muddatini belgilab kerakli ruxsatlarni berib Create personal accsess token bosib Gitlab token generatsiya qilib olamiz.
O'zingiz ishlatdigan VCSdan access token generatsiya qilib olganingizdan keyin Serverimizda ishga tushirilgan Jenkinsga kirib credentialsga ushbu tokenlarni qo'shib qo'yamiz.
-> Manage Jenkins
-> Credentials
Username-> Gitlab yoki Github username
Password Gitlab yoki Gitlabdan generatsiya qilib olgan personal access tokenni joylashtiramiz.
Jenkinsga Gitlab yoki Githubdan private repositoriyalarni klon qilib ishlashi uchun accsess tokenni joylashtirib sozlaganimizdan keyin birinchi Jenkins CI pipelineni yozishni boshlasak bo'ladi.
Discord bilan integratsiya
Discordni CI/CD pipelinelari bilan integratsiyalash dastuchilar guruhlari ichida hamkorlik va aloqani yaxshilaydi. Discord, mashhur xabar almashish platformasi, real vaqt rejimida notificationlar uchun markazlashtirilgan markaz(hub) bo'lib xizmat qiladi, tezkor javob vaqtlarini oshiradi va dasturiy ta'minotni ishlab chiqishning lifesiklini yaxshilaydi. Jenkins CI yoki har qanday CI/CD tooli Discord bilan bog'lash orqali dasturchilar to'g'ridan-to'g'ri o'zlari tanlagan Discord kanallarida build holati, test natijalari va deployment natijalari bo'yicha tezkor yangilanishlarni oladi.
Qisqa qilib aytganda biz discordni CI/CD pipelinemiz muvaffaqiyatli ishini tugatgani yoki muvaffaqiyatsiz bo'lgan xabarlarni dasturchilar guruhlariga discord orqali yetkizish uchun ishlatamiz.
Jenkins uchun
Discordni Jenkins bilan integratsiya qilish uchun Discord Notifier plaginini Jenkinsga o'rnatib olishimiz kerak.
-> Manage Jenkins
-> Plugins
-> Available plugins
Discord Notifier plaginini o'rnatib jenkins restart bo'lganidan keyin Discord server ochib serverda channel ochib webhook yaratib olamiz.
Discord kirib Add a Server bosib Server yaratib olamiz
Serverga nom berib Create bosamiz.
Discord Server yaratib olganimzidan keyin Serverimizda channel yaratib olamiz. Create Channel
Channel nomini yozamiz masalan dev-jenkins -> Create Channel
Channel ochib olganimzidan keyin Integrations bo'limga kirib Webhooksdan Create Webhook bosamiz
Webhook yaratib olganimizdan keyin uni nusxalab Copy Webhook URL olib qo'yamiz va Jenkins pipelineda ishlatish uchun olib qo'yamiz.
Discordan olgan webhookni Jenkins credendialsga qo'shamiz.
-> Manage Jenkins
-> Credentials
Gitlab Github uchun
Github bilan jenkinsni integratsiya qilish uchun ushbu video qo'llanmalardan foydalanishingiz mumkin. dev-jenkins channel ochganimizdek github yoki gitlab channel ochib webhook yaratib Gitlab yoki Github bilan integratsiya qilamiz.
Bu holda har bir repositoriyalarga discord webhook ulab chiqiladi.
Birinchi CI pipeline
Hozirchi hammasi tayyor birinchi Jenkins CI pipelinemizni yozishga tayyormiz. Jenkinsga kirib loyihamiz uchun job yaratib olamiz.
-> Creaet a job +
Enter an item name ga loyihamiz nomini yozib Pipelineni tanlab OK bosamiz
Keyingi qismda eng pastgi qatorga Pipeline qismiga quyidagi birinchi CI pipelinemizni joylashtiramiz Save qilamiz.
Jenkins CI pipeline
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: 'git-token'
}
}
}
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: env.GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: env.DISCORD_WEBHOOK
)
}
}
}
Keling pipelineni bo'laklarga bo'lib ko'rib chiqamiz. Bu Groovy-da yozilgan Jenkins Pipeline, Java Virtual Machine uchun skript tili. Keling, ushbu pipelinening asosiy qismlarini ajratamiz:
agent any
Ushbu pipeline Jenkins muhitida mavjud bo'lgan har qanday agentda ishlashi mumkin. Har qanday kalit so'z pipelineni istalgan mavjud executorda ishlashiga imkon beradi.
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
- DISCORD_WEBHOOK-> Discord webhook URL manzilini saqlaydigan credential.
- GIT_URL-> Klonlanadigan Git repositoriyaning URL manzili.
- GIT_TOKEN-> Autentifikatsiya uchun Git tokenini saqlaydigan credendial(private repositoriyalar bilan ishlash uchun).
- BRANCH_NAME-> Git repositoriyasining foydalaniladigan branchi (bu holda main).
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: 'git-token'
}
}
}
- Clean Workspace-> Ushbu bosqich ishni boshlashdan oldin workspaceni tozalaydi.
- Clone Repository-> Bu bosqich GIT_URL va BRANCH_NAME tomonidan belgilangan Git repositoriyani git-token tomonidan aniqlangan credendial yordamida klonlaydi.
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: env.GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: env.DISCORD_WEBHOOK
)
}
}
Jarayon tugallangandan so'ng (muvaffaqiyatsiz bo'lsa ham), discordSend qadami bajariladi. U DISCORD_WEBHOOK da saqlangan webhook URL manzilidan foydalanib, Discord channelga notification(xabar) yuboradi. Xabarda natija, Git repositoriyaga link va job nomi kabi ma'lumotlar mavjud.
Qisqa qilib aytganda ushbu boshlang'ich sodda pipeline ishga tushganida biinchi Clean Workspace bosqichida cleanWs() bilan worskspaceni tozalaydi keyingi Clone Repository bosqichida berilgan GIT_URL, GIT_TOKEN va BRANCH_NAME bilan Git repositoriyani klon qilib oladi. Oxirgi bosqichda pipeline muvaffaqiyatli(SUCCSES) yoki muvaffaqiyatsiz(FAILED) bo'lgani haqida Discord channelga notification(xabar) yuboradi.
Keling pipelineni ishga tushiramiz. -> Build Now
SIzda quyidagi natijha bilan muvaffaqiyatli ishga tushishi va discordga notification yuborilishi kerak.
Git repositoriyalar bilan ishlash (mono repo va multi repo)
Bizda har xil vaziyat bo'lishi mumkin loyihamiz mono repo yoki multi repo bo'lishi mumkin.
Monorepo (Monolithic Repository)-> monolithic repository
so'zining qisqartmasi monorepo - bu bir nechta loyihalar, applicationlar yoki servicelar bitta repositoriyada saqlanadigan version control system (VCS) strategiyasidir. Monorepoda barcha kodlar, kutubxonalar(library) va turli loyihalar uchun dependensilar(bog'liqliklar) bitta markaziy repositoriyada birgalikda boshqariladi. Ushbu yondashuv har bir loyiha yoki servicening o'z repositoriyasiga ega bo'lgan ko'p repositoriyali(multi-repo) sturukturasidan farq qiladi. Qisqa qilib aytganda butun bir tashkilot loyihalari bitta repositoriyada bo'ladi.
Multirepo (Multi-Repository)-> multi-repo yondashuvida har bir loyiha, application yoki service o'zining alohida repositoriyasiga ega. Har bir repositoriya ma'lum bir kod bazasi yoki servicega bag'ishlangan va loyihalar o'rtasidagi dependensilar versiya va paketlarni boshqarish orqali boshqariladi. Qisqa qilib ayganda har bir loyiha, application, service va boshqalar alohida alohida repositoriyalarda bo'ladi va bir-biriga bo'g'liklari bo'ladi.
Monorepo va multirepo yondashuvlarining kuchli va zaif tomonlari bor va ular orasidagi tanlov ko'pincha loyiha yoki tashkilotning o'ziga xos ehtiyojlari, ko'lami va rivojlanish ish oqimlariga bog'liq.
Agar biz CI/CD yozayotgan loyiha monorepo bo'lsa, bitta monoreponi o'zini clon qilib uni build qilib ishga tushira olamiz, Bu soddaroq bo'ladi chunki loyihalar, applicationlar, servicelar va boshqalar o'rtasidagi bo'gliklik(reference) bitta shu monorepo ichida bo'ladi.
Monorepo uchun Jenkins pipeline, faqat kerakli monorepo clon qilinadi holos.
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: 'git-token'
}
}
}
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: env.GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: env.DISCORD_WEBHOOK
)
}
}
}
Tashkilot loyihalari multirepo bo'lsa va biz loyihalarga CI/CD yozayotgan bo'lsak, har bir loyihada bir nechta boshqa repositoriyalarga bo'glikligi(reference) bo'ladi, shuning uchun CI/CD yozayotgan loyihamiz ishlashiga kerak bo'lgan loyiha, application,service va boshqalar repositoriyalarni ham klon qilib olishimiz va yig'ishimiz kerak bo'ladi.
Multirepo uchun Jenkins pipeline.
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
API_GIT_URL ='https://github.com/ismoilovdevml/devops-journey-api.git'
UI_GIT_URL = 'https://github.com/ismoilovdevml/devops-journey-ui.git'
SERVICE_GIT_URL = 'https://github.com/ismoilovdevml/devops-journey-service.git'
CONFIGURATIONS_GIT_URL = 'https://github.com/ismoilovdevml/devops-journey-configurations.git'
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Setup Environment') {
steps{
dir('configurations'){
git branch: BRANCH_NAME, url: CONFIGURATIONS_GIT_URL, credentialsId: 'git-token'
}
dir('devops-journey/devops-journey-ui'){
git branch: BRANCH_NAME, url: UI_GIT_URL, credentialsId: 'git-token'
}
dir('devops-journey/devops-journey-api'){
git branch: BRANCH_NAME, url: API_GIT_URL, credentialsId: 'git-token'
}
dir('devops-journey/devops-journey-service'){
git branch: BRANCH_NAME, url: SERVICE_GIT_URL, credentialsId: 'git-token'
}
sh "cp configurations/devops-journey/${BUILD_BRANCH}/MAIN.Dockerfile ./MAIN.Dockerfile"
sh "cp configurations/devops-journey/${BUILD_BRANCH}/API.Dockerfile ./API.Dockerfile"
sh "cp configurations/devops-journey/${BUILD_BRANCH}/UI.Dockerfile ./UI.Dockerfile"
sh "cp configurations/devops-journey/${BUILD_BRANCH}/SERVICE.Dockerfile ./SERVICE.Dockerfile"
}
}
}
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: env.GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: env.DISCORD_WEBHOOK
)
}
}
}
Multirepo uchun yozgan pipelinemizda o'zgarishlar quyidagicha devops-journey loyihamizda bir nechta boshqa repositoriyalarga bo'gliklari mavjuda maslaan UI, API, Service va Configurations repositoriyalarga. Ushbu loyihani Jenkins CI/CD ishga tushirishimiz uchun ushbu repositoriyalar clon qilinb yig'ishimiz va birga ishga tushirishimiz kerak. Setup Environment qadami ushbu vazifani bajaradi yani Environmentni sozlaydi kerak repositoriyalarni bir joyga yig'adi.
Ushbu namunada konfiguratsiyalar ham alohida repositoriyada saqlangani ko'rsatilgan yani configurations repositoriyada barcha loyihalar servicelar applicationlar konfiglari(masalan Dockerfayllar) branchlar nomi bilan joylashtirilgan bo'ladi. configurations repositoriyasi tuzulishiga namuna.
├── configurations
│ └── devops-journey
│ ├── main
│ │ ├── API.Dockerfile
│ │ ├── MAIN.Dockerfile
│ │ ├── SERVICE.Dockerfile
│ │ └── UI.Dockerfile
│ ├── dev
│ │ ├── API.Dockerfile
│ │ ├── MAIN.Dockerfile
│ │ ├── SERVICE.Dockerfile
│ │ └── UI.Dockerfile
│ ├── stage
│ │ ├── API.Dockerfile
│ │ ├── MAIN.Dockerfile
│ │ ├── SERVICE.Dockerfile
│ │ └── UI.Dockerfile
│ └── prod
│ ├── API.Dockerfile
│ ├── MAIN.Dockerfile
│ ├── SERVICE.Dockerfile
│ └── UI.Dockerfile
CI pipeline
Hammasi tayyor endi to'liq CI pipeline yozib ishga tushirsak bo'ladi. Bundan oldin monorepo va multi-repolar bilan ishlash ko'rsatildi loyihangizga qarab buni tanlaysiz. devops-journey (opens in a new tab) monorepo bo'lgani uchun monorepo CI/CD pipeline yozamiz lekin yuqorida multi-repo uchun ham namuna ko'rsatilgan.
Hozirgacha yozgan CI pipelinemiz quyidagicha
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: 'git-token'
}
}
}
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: env.GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: env.DISCORD_WEBHOOK
)
}
}
}
CI pipelinemizga Docker bilan ishlash bosqichini qo'shimiz kerak. Buning uchun Jenkinsga kerakli plaginlarni o'rnatib olishimiz kerak.
Pipelinemizda Docker bilan ishlash uchun quyidagi plaginlarni o'rnatib olishimiz kerak.
Docker
, Docker Common
, Docker Pipeline
, Docker API
, docker-build-step
Plaginlarni o'rnatib bo'lganingizdan keyin sozlab chiqish kerak.
-> Manage Jenkins
-> Tools
-> Docker installations
ESLATMA-> Docker bilan ishlash uchun Jenkins o'rnatilgan serverda docker ham o'rnatilgan bo'lishi kerak!
Docker bilan ishlashni sozlab chiqganimizdan keyin Jenkins pipelineda build bo'lgan docker imagelarni push qilish saqlash uchun Docker Registry ishlatamiz. Ushbu amaliyotda Dockerhub va GCR(Google Container Registry)dan foydalanish ko'rsatiladi. Dockerhub bepul versiyasida bitta private docker imagega ruxsat bor undan keyingi imagelar avtomatik public bo'ladi, private qilish uchun Dockerhub pullik obunaga a'zo bo'lish kerak. GCR Google Cloudga tegishli.
Dockerhub
Amaliyotni ushbu qismida Docker Registry uchun Dockerhub ishlatamiz shuning uchun Dockerhubdan ro'yxatdan o'tgan bo'lishingiz va Access token olgan bo'lishingiz kerak. Agar Ro'yxatdan o'tmagan bo'lsangiz ro'yxatdan o'tishingiz kerak
Sign up
bosib ro'yxatdan o'tasiz
Ro'yxatdan o'tib olganingizdan keyin Email Verification talab qilinadi. Email verifatsiya qilganingizdan keyin
-> Account Settings
-> Security
-> bo'limga o'tib Access Token
yaratib olamiz.
Access Tokenga nom berib unga Read,Write,Delete permisonlarni beramiz Generate
qilamiz.
Sizga access token generatsiya qilib berialdi va siz undan nusxa olib qo'yishingiz kerak, aks holda uni qaytib ololmaysiz. Sizga docker login qilish uchun namuna CLI command ham beriladi
docker login -u devsecopsuser4732
Jenkins pipelineda DockerHub Registrydan foydalanishimiz uchun Jenkins crdentialsga DockerHub user va tokenni qo'shib qo'yamiz.
-> Manage Jenkins
-> Credentials
-ga kirib Add credentials
ga o'tamiz.
Usernamega DockerHub usernamengizni yozasiz Passwordga esa yuqorida yaratib olgan access tokenimizni joylashtiramiz.
Dockerhubdan ro'yxatdan o'tdik, access token oldik hammasini Jenkins credentialsga dockerhub ID bilan saqladik endi Jenkins pipelinega CD(continuous delivery)qismini qo'shsak bo'ladi.
Jenkins pipelenimizga quyidagi bosqichni qo'shamiz. Bu bosqich ilovamizdan docker image yaratib, build qilib, Docker Registryga push qiladi ya'ni DockerHubga.
Pipelinega yangi environmentlar qo'shib olamiz:
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
DOCKERHUB_CREDENTIALS = credentials('dockerhub')
CONTAINER_NAME = 'devops-journey'
REGISTRY_URL = 'devsecopsuser732'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
- DOCKERHUB_CREDENTIALS -> credentialsdandan DockerHub username va access tokenni olib keladi.
- CONTAINER_NAME -> Bu loyihamizni containerda ishga tushirishda unga beriladigan nom
- REGISTRY_URL -> Dokcer Registry URL. Bizni holatimizda yani Dockerhubda bu yerda Dockerhub username yoziladi.
Dockerhub bilan ishlaydigan Jenkins CI pipelinemizni quyidagicha yangilaymiz.
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
DOCKERHUB_CREDENTIALS = credentials('dockerhub')
CONTAINER_NAME = 'devops-journey'
REGISTRY_URL = 'devsecopsuser732'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: 'git-token'
}
}
stage('Build Application') {
steps {
withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
script {
def dockerlogin = "docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD}"
sh dockerlogin
sh """
docker build . -t ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER} -f Dockerfile
docker tag ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER} ${REGISTRY_URL}/${CONTAINER_NAME}:latest
docker push ${REGISTRY_URL}/${CONTAINER_NAME}:latest
docker push ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER}
docker image rm -f ${REGISTRY_URL}/${CONTAINER_NAME}:latest
docker image rm -f ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER}
"""
}
}
}
}
}
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: env.GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: env.DISCORD_WEBHOOK
)
}
}
}
GCR(Google Container Registry)
Docker Registry sifatida GCR ishlatish uchun Google Cloud IAMdan Service Account ochib olishimiz va unga Storage Admin ruxsatini berishimiz kerak, undan keyin service accountga kirib service account key generatsiya qilib olishimiz kerak. Credentiallar Jenkins pipeline Google cloudga GCR ga kira olishi va ishlashi uchun kerak.
1-> Google Cloudga kirib Service Accountsdan service account yaratib olamiz.
-> Google Cloud -> IAM & Admin -> Service Accounts
2 -> + CREATE SERVICE ACCOUNT bosib service account yaratib olamiz.
3 -> Service account namega service accountimiz uchun nom yozamiz masalan gcr. Service account descriptionga esa description yozib DONE bosganimizdan keyin keyingi bosqichga o'tadi
4 -> Rolega Storage Admin huquqini beramiz va DONE bosib yaratib olamiz.
5 -> Service Account yaratib olganimizdan keyin Service Accountimizga(gcr) kirib KEYS qismidan ADD KEY bosib JSON formatda private key generatsiya qilib olamiz va uni yuklab olamiz.
-> KEYS -> ADD KEY -> JSON -> CREATE
7-> Yuklab olgan Service account private keyimizni Jenkins credentialsga qo'shib qo'yamiz.
-> Manage Jenkins
-> Credentials
-ga kirib Add credentials
ga o'tamiz.
8-> Google Clouddan yuklab olgan service account private keyimizni ochib ko'rsak 2chi qatorida project_id ko'rsatilgan bo'ladi uni nusxalab olib uni ham Jenkins credentialsga qo'shib qo'yamiz.
-> Manage Jenkins
-> Credentials
-ga kirib Add credentials
ga o'tamiz.
9-> Hamma kerakli keylarni Jenkins credentialsga qo'shagnimizdan keyin bizni GCR bilan ishlaydigan Jenkins pipelinemizda quyidagicha o'zgarishlar bo'ladi.
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GCR_CREDENTIALS = credentials('gcr-key')
GCP_PROJECT_ID = credentials('gcp-project-id')
CONTAINER_NAME = 'devops-journey'
REGISTRY_URL = 'gcr.io'
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: GIT_TOKEN
}
}
stage('Build and Push Docker Image') {
steps {
script {
def dockerImage = "${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:${BUILD_NUMBER}"
sh """
cat ${GCR_CREDENTIALS} | docker login -u _json_key --password-stdin https://gcr.io
docker build . -t ${dockerImage} -f Dockerfile
docker push ${dockerImage}
docker tag ${dockerImage} ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest
docker push ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest
docker image rm -f ${dockerImage}
docker image rm -f ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest
"""
}
}
}
}
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: DISCORD_WEBHOOK
)
}
}
}
Dockerhub va GCR Container registrylar uchun Jenkins CI pipelien yozdik va muvaffaqiyatli ishladi va endi CD bosqichini yani serverga deploy qilish boqichini qo'shsak bo'ladi.
CD pipeline
CI pipelineni muvaffaqiyatli yozib ishga tushirganimizdan keyin CD pipeline yozishni boshlasak bo'ladi. CD pipeline quyidagi bosqichlardan iborat Jenkins pipeline ssh-agent orqali serverga bo'glanadi va u birinchi navbatda Jenkins crdentialsda ko'rsatilgan Docker registry secretlari bilan docker login qiladi va undan keyin belgilangan docker image va belgilangan tag bilan docker registrydan pull qilib oladi agar Jenkins pipelineda belgilangan docker container nomi bilan ishlab turgan docker container ishlab turgan bo'lsa uni to'xtatib, o'chirib tozalab yangi containerni belgilangan nom va belgilangan port bilan ishga tushiradi.
Loyihamizni serverimizda ishga tushirishimiz uchun Jenkins pipeline serverga kira olishi kerak. Biz buning uchun SSH(ssh-agent) dan foydalanamiz. ssh-agent plagini Jenkinsga o'rnatib olishimiz kerak.
-> Manage Jenkins
-> Plugins
SSH Agent plagini Jenkinsga o'rnatganimizdan keyin Serverimizda ssh key generatsiya qilib Jenkins credentialsga qo'shib qo'yishimiz kerak.
Hozir esa serverimizga kirib ssh-key generatsiya qilib olamiz.
ESLATMA-> Bu yurda netflix nomli ssh key generatsiya qilinib ishtilyapti. Bu nom ixtiyoriy xoxlagan nomizni berib ishlatavering!
ssh-keygen -f ~/.ssh/netflix
ssh-keygen
buyrug'i tizimlar orasidagi xavfsiz aloqa uchun SSH (Secure Shell) kalit juftlarini yaratish uchun Unix-ga o'xshash operatsion tizimlarda qo'llaniladigan tooldir. ssh-keygen
-ni ishga tushirganingizda, siz bir juft kalit yaratasiz: public key va private key.
ssh-keygen
Bu SSH kalitlarini yaratish uchun ishlatiladigan buyruq.-f ~/.ssh/netflix
Bu yerda-f
yaratilgan kalit faylning fayl nomini bildiradi.~/.ssh/netflix
kalitlar saqlanadigan jild va fayl nomini bildiradi.~
foydalanuvchining home jildini ifodalaydi (masalan, Linuxda /home/username),~/.ssh
esa SSH kalitlarini saqlash uchun umumiy jilddir. Bu buyruqssh-keygen
-ga yangi SSH kalit juftligini yaratish va uni foydalanuvchining home jildidagi.ssh
jildida netflix sifatida saqlashni aytadi.
Buyruq bajarilgandan so'ng siz odatda ikkita faylni olasiz:
netflix
Bu boshqa tizimlarga ulanishda o'zingizni autentifikatsiya qilish uchun foydalaniladigan shaxsiy(private) kalit fayli.netflix.pub
Bu public kalit fayli. Siz ushbu faylni ushbu kalitdan foydalanishga ruxsat bermoqchi bo'lgan boshqa tizimlar/xizmatlar bilan baham ko'rishingiz mumkin.
cat netflix.pub >> authorized_keys
cat netflix.pub >> authorized_keys
Ushbu buyruq netflix.pub
faylining mazmunini authorized_keys
faylining oxiriga qo'shadi.
cat
- fayl mazmunini ko'rsatish uchun ishlatiladigan buyruq.>>
- faylga chiqish qo'shish uchun ishlatiladigan qayta yo'naltirish operatori.
authorized_keys
public kalit autentifikatsiyasi uchun SSH da qo'llaniladigan fayldir. SSH serveri ulanish so'rovini olganida, kirish public kaliti u yerda sanab o'tilgan kalitlardan biriga mos kelishini tekshirish uchun authorized_keys
faylini ko'rib chiqadi. Agar shunday bo'lsa, kirish huquqi beriladi.
Ushbu buyruqlar ketma-ketligining maqsadi netflix.pub
faylida saqlangan public kalitni avtorizatsiya qilingan kalitlar ro'yxatiga (avtorized_keys) qo'shishi. Kimda tegishli private kalit (netflix) bo'lsa, endi ushbu private kalit yordamida ushbu tizim bilan autentifikatsiya qilish mumkin. U autentifikatsiya qilish uchun o'rnatilgan public-private kalit juftligidan foydalanib, parol talab qilmasdan kirish imkonini beradi. Bu pipeline orqali serverga kirishga imkon beradi.
cat ~/.ssh/netflix
Ushbu buyruq netflix nomli ssh keyimizni private keyni ko'rsatadi biz undan nusxa olib qo'yamiz.
Serverda ssh-key generatsiya qilib oldik endi Jenkins credentialsga qo'shsak bo'ladi.
-> Manage Jenkins
-> Credentials
Kind ->
SSH Userame with private keyID->
server-ssh(ssh keyni pipelineda xavfsiz quyidagi ID bilan ishlatamiz)Username->
server username kiritiladi(server usernameni bilish uchun buyruq)
whoami
Private Key->
netflix private keyni joylashtiramiz.
SSh key generatsiya qilib sozlab oldik endi Serverga kirib Docker registrydan imageni pull qilib olib uni run qiladigan bosqich qo'shishimiz kerak.
Jenkins pipeleni Serverga kira olishi uchun 2 ta Jenkins credentials yaratish kerak bular: Server username'si va Server IP manzilidir.
-> Manage Jenkins
-> Credentials
Bu qismda Secret
ga serverimiz username'si yoziladi(whoami buyrug'i bilan bilib olishingiz mumkin)
Bu qismda esa Secret
ga Serverimiz IP manzilini yozishimiz kerak.
Dockerhub
ESLATMA-> Ushbu CD qism asosan Dockerhub va boshqa container registrylarda ishlash uchun moslashtirilgan! GCR uchun quyidagi qismga o'ting
1-> Endi Serverimizga kerakli environment
larni qo'shib chiqishimiz kerak.
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
DOCKERHUB_CREDENTIALS = credentials('dockerhub')
CONTAINER_NAME = 'devops-journey'
REGISTRY_URL = 'devsecopsuser732'
GIT_TOKEN = credentials('git-token')
SERVER_USERNAME = credentials('server-username')
SERVER_IP = credentials('server-ip')
SSH_CREDENTIALS = credentials('server-ssh')
BRANCH_NAME = 'main'
}
2-> Deploy Server bosqichi
stage('Deploy Server') {
steps {
withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
script {
sshagent (credentials: ['server-ssh']) {
sh """
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP} '\
docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD} && \
docker pull ${REGISTRY_URL}/${CONTAINER_NAME}:latest && \
docker stop ${CONTAINER_NAME} || true && \
docker rm ${CONTAINER_NAME} || true && \
docker run -d -p 3000:3000 --name ${CONTAINER_NAME} --restart always ${REGISTRY_URL}/${CONTAINER_NAME}:latest '
"""
}
}
}
}
}
ushbu Deploy Server bosqichi quyidagicha ishlaydi.
withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) { }
withCredentials
orqali Jenkinsdagi dockerhub
crdentialidan docker username va docker password ajratib olinib DOCKER_USERNAME
va DOCKER_PASSWORD
biriktiriladi bu docker login qilib Dockerhubga kira olish uchun. sshagent (credentials: ['server-ssh']) { }
qismida Jenkinsga o'rnatgan ssh-agent plagini orqali serverga ulanib kiramiz va berilgan buyruqlarni ketma-ket ishga tushurishni boshlaydi.
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP}
ushbu buyruq bilan serverga kiramiz.docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD}
Berilgan crdentials orqali Docker registry yani Dockerhubga login qiladi.docker pull ${REGISTRY_URL}/${CONTAINER_NAME}:latest
yangi docker imageni pull qilib serverga tortib oladi.docker stop ${CONTAINER_NAME} || true
berilgan container nomi bilan ishlab turgan container bo'lsa uni to'xtadi.docker rm ${CONTAINER_NAME} || true
berilgan container nomi bilan ishlab turgan container bo'lsa uni o'chiradi.(yangi docker imageni ishga tushirish uchun)docker run -d -p 4001:4001 --name ${CONTAINER_NAME} --restart always ${REGISTRY_URL}/${CONTAINER_NAME}:latest
berilgan containerni belgilangan port va nom bilan docker registrydan oxirgi marta pull qilib olingan docker imageni run qilib ishga tushirib qo'yadi.
Qisqa qilib aytganda asosiy ish quyidagicha ssh-agent orqali serverga kiradi va docker login qilib berilgan imageni pull qilib tortib oladi shu nom bilan ishlab turgan eski containerni to'xtatib o'chiradi va yangi containerni berilgan port berilgan nom bilan ishga tushirib qo'yadi.
GCR
1-> GCR uchun environment
qismi.
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GCR_CREDENTIALS = credentials('gcr-key')
GCP_PROJECT_ID = credentials('gcp-project-id')
CONTAINER_NAME = 'devops-journey'
REGISTRY_URL = 'gcr.io'
SERVER_USERNAME = credentials('server-username')
SERVER_IP = credentials('server-ip')
SSH_CREDENTIALS = credentials('server-ssh')
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
2-> GCR uchun Deploy Server
bosqichi.
stage('Deploy to Server') {
steps {
script {
sshagent(credentials: ['server-ssh']) {
// Copy the GCR credentials to the server
sh "scp -o StrictHostKeyChecking=no ${GCR_CREDENTIALS} ${SERVER_USERNAME}@${SERVER_IP}:/tmp/gcr-key.json"
// Log in to GCR on the server using the copied credentials
sh """
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP} \
'cat /tmp/gcr-key.json | docker login -u _json_key --password-stdin https://gcr.io'
"""
// Continue with the rest of the deployment steps
sh """
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP} '\
docker pull ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest && \
docker stop ${CONTAINER_NAME} || true && \
docker rm ${CONTAINER_NAME} || true && \
docker run -d -p 3000:3000 --name ${CONTAINER_NAME} --restart always ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest '
"""
}
}
}
}
GCRga moslab yozilgan CD pipeline quyidagicha ishlaydi. Esingizda bo'lsa bizda Google Cloud IAMdan Service Account ochib undan private .json key generatsiya qilib olgandik va uni Jenkins crdentialsga fayl sifatida qo'shgandik. GCR registryga faqat shu berilgann .json private key fayl bilan docker login qila olamiz shuning shu secret faylni scp orqali serverga olib o'tamiz va shu private .json fayl bilan login qilamiz undan keyin docker imageni pull qilib olib eski containerni to'xtatib,o'chirib yangi containerni run qilib ishga tushirib qo'yamiz. Hammasi bajarilganidan keyin serverga ko'chirib o'tkazgan private .json faylimizni xavfsizlik uchun o'chirib tashlaymiz va natija haqida discord serverga notification yuboramiz.
Xulosa
Dockerhub bilan ishlaydigan to'liq CI/CD Jenkins pipeline
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
DOCKERHUB_CREDENTIALS = credentials('dockerhub')
CONTAINER_NAME = 'devops-journey'
REGISTRY_URL = 'devsecopsuser732'
GIT_TOKEN = credentials('git-token')
SERVER_USERNAME = credentials('server-username')
SERVER_IP = credentials('server-ip')
SSH_CREDENTIALS = credentials('server-ssh')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: 'git-token'
}
}
stage('Build Application') {
steps {
withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
script {
def dockerlogin = "docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD}"
sh dockerlogin
sh """
docker build . -t ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER} -f Dockerfile
docker tag ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER} ${REGISTRY_URL}/${CONTAINER_NAME}:latest
docker push ${REGISTRY_URL}/${CONTAINER_NAME}:latest
docker push ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER}
docker image rm -f ${REGISTRY_URL}/${CONTAINER_NAME}:latest
docker image rm -f ${REGISTRY_URL}/${CONTAINER_NAME}:${BUILD_NUMBER}
"""
}
}
}
}
stage('Deploy Server') {
steps {
withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
script {
sshagent (credentials: ['server-ssh']) {
sh """
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP} '\
docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD} && \
docker pull ${REGISTRY_URL}/${CONTAINER_NAME}:latest && \
docker stop ${CONTAINER_NAME} || true && \
docker rm ${CONTAINER_NAME} || true && \
docker run -d -p 3000:3000 --name ${CONTAINER_NAME} --restart always ${REGISTRY_URL}/${CONTAINER_NAME}:latest '
"""
}
}
}
}
}
}
post {
always {
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: env.GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: env.DISCORD_WEBHOOK
)
}
}
}
GCR uchun
pipeline {
agent any
environment {
DISCORD_WEBHOOK = credentials('discord-webhook')
GIT_URL = 'https://github.com/ismoilovdevml/devops-journey.git'
GCR_CREDENTIALS = credentials('gcr-key')
GCP_PROJECT_ID = credentials('gcp-project-id')
CONTAINER_NAME = 'devops-journey'
REGISTRY_URL = 'gcr.io'
SERVER_USERNAME = credentials('server-username')
SERVER_IP = credentials('server-ip')
SSH_CREDENTIALS = credentials('server-ssh')
GIT_TOKEN = credentials('git-token')
BRANCH_NAME = 'main'
}
stages {
stage('Clean Workspace') {
steps {
cleanWs()
}
}
stage('Clone Repository') {
steps {
git branch: BRANCH_NAME, url: GIT_URL, credentialsId: 'git-token'
}
}
stage('Build and Push Docker Image') {
steps {
script {
def dockerImage = "${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:${BUILD_NUMBER}"
sh """
cat ${GCR_CREDENTIALS} | docker login -u _json_key --password-stdin https://gcr.io
docker build . -t ${dockerImage} -f Dockerfile
docker push ${dockerImage}
docker tag ${dockerImage} ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest
docker push ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest
docker image rm -f ${dockerImage}
docker image rm -f ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest
"""
}
}
}
stage('Deploy to Server') {
steps {
script {
sshagent(credentials: ['server-ssh']) {
// Copy the GCR credentials to the server
sh "scp -o StrictHostKeyChecking=no ${GCR_CREDENTIALS} ${SERVER_USERNAME}@${SERVER_IP}:/tmp/gcr-key.json"
// Log in to GCR on the server using the copied credentials
sh """
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP} \
'cat /tmp/gcr-key.json | docker login -u _json_key --password-stdin https://gcr.io'
"""
// Continue with the rest of the deployment steps
sh """
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP} '\
docker pull ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest && \
docker stop ${CONTAINER_NAME} || true && \
docker rm ${CONTAINER_NAME} || true && \
docker run -d -p 3000:3000 --name ${CONTAINER_NAME} --restart always ${REGISTRY_URL}/${GCP_PROJECT_ID}/${CONTAINER_NAME}:latest '
"""
}
}
}
}
}
post {
always {
script {
try {
// Delete the copied GCR credentials from the server
sshagent(credentials: ['server-ssh']) {
sh """
ssh -o StrictHostKeyChecking=no ${SERVER_USERNAME}@${SERVER_IP} \
'rm /tmp/gcr-key.json'
"""
}
} catch (Exception e) {
echo "Error cleaning up GCR credentials: ${e.message}"
currentBuild.result = 'FAILURE' // Set build result to FAILURE in case of errors
} finally {
// Send Discord notification regardless of the build result
discordSend(
description: "Jenkins Pipeline Build ${currentBuild.currentResult}",
link: GIT_URL,
result: currentBuild.currentResult,
title: JOB_NAME,
webhookURL: DISCORD_WEBHOOK
)
}
}
}
}
}
DEV, STAGE, PROD
Loyihani uch bosqichda DEV, STAGE, PROD bosqichli qilish uchun quyidagi usuldan foydalanishimiz mumkin, yani jenkinsda loyiha nomli jild(folder) ochib olamiz va dev, stage, prod nomli joblar ochamiz dev pipelineda dev serverlar va gitdagi dev branch stage ham shunday gitdagi stage branch va stage serverlar va prod main branch va yoki prod branchdan kodlarni olib prod serverlarga deploy qilib qo'yadi.
1-> Jenkinsda loyiha nomli folder ochib olamiz masalan devops-journey -> Create a job -> Folder
loyiha nomini yozamiz va Folderni tanlab OK bosamiz.
Undan keyingi ochilgan oynada Folderga Description yozib yaratib olamiz
Keyin bizda quyidagi oyna ochiladi
Endi dev,sateg,prod nomli joblar yaratib olamiz va shunga moslab configuratsiya qilib olamiz. Masalan dev jobda dev nomli branchdagi kodlarni olib uni build qilib dev serverda ishga tushiradi, qolgan stage va prod ham xuddi shunday ishlaydi.
Qo'shimcha
Ushbu loyiha GitHub repositoriyasi: github.com/ismoilovdevml/devops-journey (opens in a new tab)
Qo'shimcha Resurslar
- Linux Serverlarga Jenkins o'rnatish (opens in a new tab)
- Github Actions CI/CD (opens in a new tab)
- Github Actions bilan Anroid CI/CD (opens in a new tab)
- Github Actions bilan Flutter CI/CD (opens in a new tab)
- Gitlab CI | Releaselar va Integrationlar (opens in a new tab)
- Kubernetes CI/CD | GitHub Actions + Argo CD | GitOps (opens in a new tab)
Sana: 2024.01.18 (2024-yil 18-yanvar)
Oxirgi yangilanish: 2024.01.19(2024-yil 19-yanvar)
Muallif: Otabek Ismoilov
Telegram (opens in a new tab) | GitHub (opens in a new tab) | LinkedIn (opens in a new tab) |
---|