Come raccogliere progetti in Jenkins se hai bisogno di molti ambienti diversi

Come raccogliere progetti in Jenkins se hai bisogno di molti ambienti diversi

Ci sono molti articoli su Habré su Jenkins, ma pochi descrivono esempi di come funzionano Jenkins e gli agenti docker. Tutti gli strumenti più diffusi per la creazione di progetti come Drone.io, Pipeline Bitbucket, GitLab, Azioni GitHub e altri, possono raccogliere tutto in contenitori. Ma che dire di Jenkins?

Oggi c'è una soluzione al problema: Jenkins 2 è un ottimo modo per lavorare Agenti Docker. In questo articolo voglio condividere la mia esperienza e mostrare come puoi farlo da solo.

Perché ho iniziato a risolvere questo problema?

Visto che siamo in compagnia Citronio Poiché utilizziamo molte tecnologie diverse, dobbiamo mantenere diverse versioni di Node.JS, Gradle, Ruby, JDK e altri sulla macchina di assemblaggio. Ma spesso i conflitti di versione non possono essere evitati. Sì, avrai ragione se dici che ci sono vari gestori di versioni come nvm, rvm, ma con loro non tutto è così fluido e queste soluzioni hanno problemi:

  • una grande quantità di runtime che gli sviluppatori dimenticano di pulire;
  • ci sono conflitti tra diverse versioni degli stessi runtime;
  • Ogni sviluppatore ha bisogno di un diverso set di componenti.

Ci sono altri problemi, ma lascia che ti parli della soluzione.

Jenkins in Docker

Poiché Docker è ormai ben consolidato nel mondo dello sviluppo, quasi tutto può essere eseguito utilizzando Docker. La mia soluzione è avere Jenkins in Docker ed essere in grado di eseguire altri contenitori Docker. Questa domanda ha cominciato a essere posta nel 2013 nell'articolo “Docker ora può essere eseguito all'interno di Docker«.

In breve, devi solo installare Docker stesso in un contenitore funzionante e montare il file /var/run/docker.sock.

Ecco un esempio di Dockerfile che si è rivelato per 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

Pertanto, abbiamo ottenuto un contenitore Docker in grado di eseguire comandi Docker sul computer host.

Costruisci la configurazione

Non molto tempo fa Jenkins ha avuto l'opportunità di descrivere le sue regole utilizzando Conduttura sintassi, che rende abbastanza semplice modificare lo script di compilazione e memorizzarlo nel repository.

Inseriamo quindi un apposito Dockerfile nel repository stesso, che conterrà tutte le librerie necessarie per la build. In questo modo, lo sviluppatore stesso può preparare un ambiente ripetibile e non dovrà chiedere a OPS di installare una versione specifica di Node.JS sull'host.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Questa immagine build è adatta per la maggior parte delle applicazioni Node.JS. Cosa succede se, ad esempio, hai bisogno di un'immagine per un progetto JVM con uno scanner Sonar incluso al suo interno? Sei libero di scegliere i componenti necessari per il montaggio.

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/

Abbiamo descritto l'ambiente di assembly, ma cosa c'entra Jenkins? E gli agenti Jenkins possono lavorare con tali immagini Docker e crearle internamente.

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"
    }
}

direttiva agent utilizza la proprietà dockerdove puoi specificare:

  • il nome del contenitore dell'assembly in base alla politica di denominazione;
  • argomenti necessari per eseguire il contenitore di compilazione, dove nel nostro caso montiamo la directory corrente come directory all'interno del contenitore.

E già nei passaggi di build indichiamo quali comandi eseguire all'interno del build agent Docker. Può trattarsi di qualsiasi cosa, quindi avvio anche la distribuzione dell'applicazione utilizzando ansible.

Di seguito voglio mostrare un Jenkinsfile generico che può essere creato da una semplice applicazione 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()
        }
    }

}

Quello che è successo?

Grazie a questo metodo abbiamo risolto i seguenti problemi:

  • il tempo di configurazione dell'assemblaggio dell'ambiente è ridotto a 10 - 15 minuti per progetto;
  • un ambiente di creazione dell'applicazione completamente ripetibile, poiché puoi crearlo in questo modo sul tuo computer locale;
  • non ci sono problemi con conflitti tra diverse versioni degli strumenti di assemblaggio;
  • sempre uno spazio di lavoro pulito che non si intasi.

La soluzione in sé è semplice ed ovvia e permette di ottenere alcuni vantaggi. Sì, la soglia di ingresso è leggermente aumentata rispetto ai semplici comandi per gli assiemi, ma ora c'è la garanzia che verrà sempre costruito e lo sviluppatore stesso potrà scegliere tutto ciò che è necessario per il suo processo di costruzione.

Puoi anche utilizzare l'immagine che ho raccolto Jenkins+Docker. Tutte le fonti sono aperte e si trovano su rmuhamedgaliev/jenkins_docker.

Durante la stesura di questo articolo è nata una discussione sull'utilizzo degli agenti su server remoti in modo da non caricare il nodo master utilizzando un plugin plug-in docker. Ma di questo parlerò in futuro.

Fonte: habr.com

Aggiungi un commento