Dockerize Jenkins Pipeline ile Continuous Integration ve Continuous Delivery (Tutorial)

Continuous Integration ve Continuous Delivery yazılım endüstrisinde son yıllarda, özellikle cloud ve container teknolojilerindeki gelişmelerle en önemli konular arasında yer almaya başladı. Bu noktada Docker, Kubernetes, OpenShift gibi container teknolojileri ve Jenkins gibi otomasyon sunucuları yazılımcıların işini oldukça kolaylaştırmıştır.
 
Bir repository oluşturdum ve uygulama derleme, test, deploy etme; kod kalitesine dair rapor alma, docker image oluşturma ve Docker Hub’a pushlama gibi işlemleri Docker gibi bir container teknolojisini kullanarak nasıl otomatize edebiliriz sorusuna cevap vermeye çalıştım.
 
Bu örnekteki amacımız, Continuous Integration ve Continuoud Delivery yaklaşımıyla, depomuza yapılacak her push sonrası bu adımların tetiklenerek bir pipeline akışında gerçekleşmesini sağlamak. Toprarlarsak, aşağıdaki süreçleri otomatik yönetmek istiyoruz:
 

  • Kodun checkout edilmesi
  • Testlerin koşturulması
  • Kodun derlenmesi
  • Sonarqube analizi
  • Docker imajının oluşturulması
  • Oluşturulan imajın Docker Hub’a pushlanması
  • İmaj pull ve run işlemlerinin gerçekleştirilmesi

 

İlk adım: Container’ları ayağa kaldırmak

 
Amaçlarımızdan biri sonarqube raporu elde etmek olduğundan, kendisi de bir container’da koşacak Jenkins’ten Sonarqube container’ına erişmemiz gerekiyor. Bu sebeple docker compose kullanacağız.

docker-compose.yml

version: '3.2'
services:
  sonarqube:
    build:
      context: sonarqube/
    ports:
      - 9000:9000
      - 9092:9092
    container_name: sonarqube
  jenkins:
    build:
      context: jenkins/
    privileged: true
    user: root
    ports:
      - 8080:8080
      - 50000:50000
    container_name: jenkins
    volumes:
      - /tmp/jenkins:/var/jenkins_home #tmp dizininin sistem yeniden başlatıldığında temizleneceğini unutmayın
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - sonarqube

 

Compose dosyasında Sonarqube ve Jenkins container’larının Dockerfile dosya dizinlerinin, context alanında tanımlandığına dikkat edin. İlgili dosyaların içeriği aşağıdaki gibidir.

FROM sonarqube:6.7-alpine

jenkins/Dockerfile

FROM jenkins:2.60.3

 

Aşağıdaki komutu docker-compose.yml dosyasıyla aynı dizinde koşturursak, Sonarqube ve Jenkins container’larının ayağa kalktığını görürüz.

 

docker-compose -f docker-compose.yml up --build
docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED              STATUS              PORTS                                              NAMES
87105432d655        pipeline_jenkins     "/bin/tini -- /usr..."   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp   jenkins
f5bed5ba3266        pipeline_sonarqube   "./bin/run.sh"           About a minute ago   Up About a minute   0.0.0.0:9000->9000/tcp, 0.0.0.0:9092->9092/tcp     sonarqube

 

GitHub konfigürasyonu

 

Depomuza yapılacak her push sonrası, tanımlayacağımız pipeline’nın tetiklenmesini istediğimizden; GitHub üzerinde Jenkins Github webhook‘u çağıracak bir servis tanımlamalıyız. Bunun için Settings -> Integrations & services menüsünde Add service altında Jenkins GitHub plugini seçiyoruz.

 

Sonrasında, dockerize Jenkins sunucumuzun URL’ine /github-webhook/ ekleyerek Jenkins URL olarak tanımlıyor ve add service diyoruz.

 

Sonraki adım, Jenkins kullanıcısı için bir SSH key üretip Deploy keys olarak depomuza eklemek.

 

 

Bu adımlar doğru atıldığında, GitHub’a yapılacak SSH bağlantı isteği aşağıdakine benzer bir sonuç döndürmeli.

 


ssh git@github.com
PTY allocation request failed on channel 0
Hi <github kullanıcı adınız>/<repository adınız>! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.

 

Jenkins konfigürasyonu

Docker compose dosyasında Jenkins’i 8080 portunda koşacak biçimde tanımlamıştık. http://localhost:8080 adresini ziyaret ettiğimizde aşağıdaki gibi bir ekran görüyor olmalıyız.

 

Sisteme giriş için admin şifresine ihtiyacımız var. Admin şifresi /var/jenkins_home/secrets/initialAdminPassword dizininde depolanıyor. Ayrıca söz konusu şifre, Jenkins ayağa kalkarken konsola da çıktılanıyor.

jenkins      | *************************************************************
jenkins      |
jenkins      | Jenkins initial setup is required. An admin user has been created and a password generated.
jenkins      | Please use the following password to proceed to installation:
jenkins      |
jenkins      | 45638c79cecd4f43962da2933980197e
jenkins      |
jenkins      | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
jenkins      |
jenkins      | *************************************************************

 

İlgili şifreye container içinden erişmek için.

docker exec -it jenkins sh
/ $ cat /var/jenkins_home/secrets/initialAdminPassword

 

Giriş sonrası bize önerilen pluginleri indirip, admin kullanıcısını tanımlıyoruz.

 

 

Save and Finish ve Start using Jenkins dedikten sonra Jenkins ana sayfasını görüyor olmalıyız. Yazının girişinde ifade ettiğimiz amaçlarımızdan biri, dockerize Jenkins içinde docker imaj oluşturabilmekti. Docker compose dosyasında yaptığımız volume atamasına dikkat edin.

- /var/run/docker.sock:/var/run/docker.sock

Buradaki amaç, Docker Daemon ile kurulumunu birazdan sağlayacağımız Docker Client‘ın socket üzerinden iletişimini sağlamak. Docker client gibi, kodumuzu derlemek için Maven aracına da ihtiyacımız var. Bu araçların kurulumu için Manage Jenkins -> Global Tool Configuration menüsünü ziyaret ediyoruz.

Install automatically checkbox’ını işaretliyoruz. Böylece bu araçlar, scriptimiz(Jenkins file) ilk koştuğunda Jenkins tarafından indirilecektir. Maven için myMaven Docker için myDocker isim tanımlamalarını yaptık. Scriptimiz içinde bu araçlara bu isimlerle erişeceğiz.

 

Scriptimiz içinde ayrıca checkout ve docker hub push işlemlerini gerçekleştireceğimizden, eğer private bir repoya erişilecekse bu iki platforma dair, değilse sadece Docker Hub’a dair credentials tanımlarının yapılması gerekiyor. Bunun için Jenkins ana sayfasında Credentials -> Global credentials (unrestricted) -> Add Credentials altında tanımlamalarımızı yapıyoruz.

ID alanına girdiğimiz değeri Docker login işlemi için script dosyamızda kullanacağız. Artık Jenkins ana sayfasında New Item menüsü altında pipeline’ımızı tanımlamaya başlayabiliriz.

Bu adımda, pipeline’ımızın her push sonrası Github hook çağrısıyla otomatik tetiklenmesi için GitHub hook trigger for GITScm pooling opsiyonunu seçiyoruz.

Ayrıca Pipeline sekmesinde, Definition olarak Pipeline script from SCM opsiyonunu belirliyor, Repository URL olarak depomuzun clone URL’ini, kullanacağımız branch ismimizi, son adımda da script dosyamızın(Jenkins file) lokasyonunu tanımlıyoruz.

Bundan sonra, depomuza bir push yapıldığında veya manuel olarak Build Now dediğimizde pipeline’ımız tetiklenecek ve script dosyamızda tanımladığımız adımlar işletilecektir.

 

Jenkins dosyasının önemli noktalarına yakından bakış

stage('Initialize'){
    def dockerHome = tool 'myDocker'
    def mavenHome  = tool 'myMaven'
    env.PATH = "${dockerHome}/bin:${mavenHome}/bin:${env.PATH}"
}

Global Tool Configuration altında tanımladığımız Maven ve Docker araçlarını script içinde kullanabilmek için bu araçları PATH ortam değişkenine ekliyoruz. Tool ismi olarak yaptığımız tanımladaki isimleri kullandığımıza dikkat edin.

stage('Push to Docker Registry'){
    withCredentials([usernamePassword(credentialsId: 'dockerHubAccount', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
        pushToImage(CONTAINER_NAME, CONTAINER_TAG, USERNAME, PASSWORD)
    }
}

Jenkins Credentials Binding Plugin tarafından sağlanan withCredentials, tanımlanan credentials bilgisini değişkenlere bind etmektedir. dockerHubAccount değerinin credentialsId parametresiyle geçildiğine dikkat edin. dockerHubAccount değerini Credentials -> Global credentials (unrestricted) -> Add Credentials menüsü altında Docker Hub credentials tanımında ID değeri olarak belirlemiştik. Söz konusu ID’yi withCredentials‘a geçirerek, login işlemi için Docker Hub username ve password bilgisine erişmiş oluyoruz.

 

Sonarqube configuration

Sonarqube için pom.xml’de aşağıdaki tanımlamaları yaptık.

<sonar.host.url>http://sonarqube:9000</sonar.host.url>
...
<dependencies>
...
    <dependency>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>sonar-maven-plugin</artifactId>
        <version>2.7.1</version>
        <type>maven-plugin</type>
    </dependency>
...
</dependencies>

Docker compose dosyasında Sonarqube container’ına sonarqube ismini vediğimizden, sonar erişim URL’i http://sonarqube:9000 olarak tanımlandı.

Evet, sözün sonuna geldik. Sizinle ele aldığımız konunun bütün detaylarını içeren bir tutorial paylaşmaya çalıştım. Umarım işinize yarar. Bir başka vesileyle görüşünceye dek hoşçakalın.

No Comments

Post a Comment

Comment
Name
Email
Website