Cum să colectați proiecte în Jenkins dacă aveți nevoie de multe medii diferite

Cum să colectați proiecte în Jenkins dacă aveți nevoie de multe medii diferite

Există multe articole despre Habré despre Jenkins, dar puține descriu exemple despre cum funcționează Jenkins și agenții docker. Toate instrumentele populare de construire a proiectelor, cum ar fi Drone.io, Conducta Bitbucket, GitLab, Acțiuni GitHub iar altele, pot colecta totul în containere. Dar ce zici de Jenkins?

Astăzi există o soluție la problemă: Jenkins 2 este grozav să lucreze cu Agenți Docker. În acest articol vreau să împărtășesc experiența mea și să arăt cum poți să o faci singur.

De ce am început să rezolv această problemă?

Din moment ce suntem in companie Citronium Deoarece folosim multe tehnologii diferite, trebuie să păstrăm diferite versiuni ale Node.JS, Gradle, Ruby, JDK și altele pe mașina de asamblare. Dar adesea conflictele de versiuni nu pot fi evitate. Da, veți avea dreptate dacă spuneți că există diverși manageri de versiuni precum nvm, rvm, dar nu totul este atât de bine cu ei și aceste soluții au probleme:

  • o cantitate mare de timp de rulare pe care dezvoltatorii uită să o curețe;
  • există conflicte între diferite versiuni ale acelorași runtime;
  • Fiecare dezvoltator are nevoie de un set diferit de componente.

Sunt și alte probleme, dar să vă spun despre soluție.

Jenkins în Docker

Deoarece Docker este acum bine stabilit în lumea dezvoltării, aproape orice poate fi rulat folosind Docker. Soluția mea este să am Jenkins în Docker și să pot rula alte containere Docker. Această întrebare a început să fie pusă încă din 2013 în articolul „Docker poate rula acum în Docker“.

Pe scurt, trebuie doar să instalați Docker într-un container funcțional și să montați fișierul /var/run/docker.sock.

Iată un exemplu Dockerfile care s-a dovedit pentru Jenkins.

FROM jenkins/jenkins:lts

USER root

RUN apt-get update && 

apt-get -y install apt-transport-https 
     ca-certificates 
     curl 
     gnupg2 
     git 
     software-properties-common && 
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && 
add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") 
   $(lsb_release -cs) 
   stable" && 
apt-get update && 
apt-get -y install docker-ce && 
usermod -aG docker jenkins

RUN curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose 

RUN apt-get clean autoclean && apt-get autoremove —yes && rm -rf /var/lib/{apt,dpkg,cache,log}/

USER jenkins

Astfel, avem un container Docker care poate executa comenzi Docker pe mașina gazdă.

Configurare de construcție

Nu cu mult timp în urmă, Jenkins a avut ocazia să-și descrie regulile folosind Conductă sintaxă, ceea ce face destul de ușor să schimbați scriptul de construcție și să îl stocați în depozit.

Deci, să punem un Dockerfile special în depozitul în sine, care va conține toate bibliotecile necesare construirii. În acest fel, dezvoltatorul însuși poate pregăti un mediu repetabil și nu va trebui să solicite OPS să instaleze o anumită versiune de Node.JS pe gazdă.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Această imagine de compilare este potrivită pentru majoritatea aplicațiilor Node.JS. Ce se întâmplă dacă, de exemplu, aveți nevoie de o imagine pentru un proiect JVM cu un scaner Sonar inclus în interior? Sunteți liber să alegeți componentele de care aveți nevoie pentru asamblare.

FROM adoptopenjdk/openjdk12:latest

RUN apt update 
    && apt install -y 
        bash unzip wget

RUN mkdir -p /usr/local/sonarscanner 
    && cd /usr/local/sonarscanner 
    && wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.3.0.1492-linux.zip 
    && unzip sonar-scanner-cli-3.3.0.1492-linux.zip 
    && mv sonar-scanner-3.3.0.1492-linux/* ./ 
    && rm sonar-scanner-cli-3.3.0.1492-linux.zip 
    && rm -rf sonar-scanner-3.3.0.1492-linux 
    && ln -s /usr/local/sonarscanner/bin/sonar-scanner /usr/local/bin/sonar-scanner

ENV PATH $PATH:/usr/local/sonarscanner/bin/
ENV SONAR_RUNNER_HOME /usr/local/sonarscanner/bin/

Am descris mediul de asamblare, dar ce legătură are Jenkins cu el? Iar agenții Jenkins pot lucra cu astfel de imagini Docker și le pot construi intern.

stage("Build project") {
    agent {
        docker {
            image "project-build:${DOCKER_IMAGE_BRANCH}"
            args "-v ${PWD}:/usr/src/app -w /usr/src/app"
            reuseNode true
            label "build-image"
        }
    }
    steps {
        sh "yarn"
        sh "yarn build"
    }
}

Directivă agent folosește proprietatea dockerunde poti specifica:

  • numele containerului de asamblare conform politicii dvs. de denumire;
  • argumentele necesare pentru a rula containerul de compilare, unde în cazul nostru montem directorul curent ca director în interiorul containerului.

Și deja în pașii de construire indicăm ce comenzi să executăm în agentul de compilare Docker. Acesta poate fi orice, așa că lansez și implementarea aplicației folosind ansible.

Mai jos vreau să arăt un fișier Jenkins generic pe care îl poate construi o aplicație simplă Node.JS.

def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""

pipeline { 
    options {
        buildDiscarder(
            logRotator(
                artifactDaysToKeepStr: "",
                artifactNumToKeepStr: "",
                daysToKeepStr: "",
                numToKeepStr: "10"
            )
        )
        disableConcurrentBuilds()
    }

    agent any

    stages {

        stage("Prepare build image") {
            steps {
                sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
            }
        }

        stage("Build project") {
            agent {
                docker {
                    image "project-build:${DOCKER_IMAGE_BRANCH}"
                    args "-v ${PWD}:/usr/src/app -w /usr/src/app"
                    reuseNode true
                    label "build-image"
                }
            }
            steps {
                sh "yarn"
                sh "yarn build"
            }
        }

    post {
        always {
            step([$class: "WsCleanup"])
            cleanWs()
        }
    }

}

Ce s-a întâmplat?

Datorită acestei metode, am rezolvat următoarele probleme:

  • timpul de configurare a asamblarii mediului este redus la 10 - 15 minute per proiect;
  • un mediu de construire a aplicației complet repetabil, deoarece o puteți construi în acest fel pe computerul local;
  • nu există probleme cu conflictele între diferite versiuni de instrumente de asamblare;
  • întotdeauna un spațiu de lucru curat, care nu se înfundă.

Soluția în sine este simplă și evidentă și vă permite să obțineți câteva avantaje. Da, pragul de intrare a crescut puțin în comparație cu comenzile simple pentru ansambluri, dar acum există garanția că va fi întotdeauna construit și dezvoltatorul însuși poate alege tot ceea ce este necesar pentru procesul său de construire.

Puteți folosi și imaginea pe care am colectat-o Jenkins + Docker. Toate sursele sunt deschise și localizate la rmuhamedgaliev/jenkins_docker.

În timpul scrierii acestui articol, a apărut o discuție despre utilizarea agenților pe servere la distanță pentru a nu încărca nodul principal folosind un plugin docker-plugin. Dar despre asta voi vorbi în viitor.

Sursa: www.habr.com

Adauga un comentariu