Comment collecter des projets dans Jenkins si vous avez besoin de nombreux environnements différents

Comment collecter des projets dans Jenkins si vous avez besoin de nombreux environnements différents

Il existe de nombreux articles sur Habré à propos de Jenkins, mais peu décrivent des exemples du fonctionnement de Jenkins et des agents Docker. Tous les outils de création de projets populaires comme Drone.io, Pipeline Bitbucket, gitlab ce, Actions GitHub et d'autres, peuvent tout collecter dans des conteneurs. Mais qu'en est-il de Jenkins ?

Il existe aujourd'hui une solution au problème : Jenkins 2 est excellent pour travailler avec Agents Dockers. Dans cet article, je souhaite partager mon expérience et montrer comment vous pouvez le faire vous-même.

Pourquoi ai-je commencé à résoudre ce problème ?

Puisque nous sommes en compagnie Citronium Parce que nous utilisons de nombreuses technologies différentes, nous devons conserver différentes versions de Node.JS, Gradle, Ruby, JDK et autres sur la machine d'assemblage. Mais souvent, les conflits de versions ne peuvent être évités. Oui, vous aurez raison si vous dites qu'il existe différents gestionnaires de versions comme nvm, rvm, mais tout n'est pas aussi fluide avec eux et ces solutions ont des problèmes :

  • une grande quantité de temps d'exécution que les développeurs oublient de nettoyer ;
  • il existe des conflits entre différentes versions des mêmes environnements d'exécution ;
  • Chaque développeur a besoin d'un ensemble différent de composants.

Il existe d'autres problèmes, mais laissez-moi vous parler de la solution.

Jenkins dans Docker

Puisque Docker est désormais bien implanté dans le monde du développement, presque tout peut être exécuté avec Docker. Ma solution est d'avoir Jenkins dans Docker et de pouvoir exécuter d'autres conteneurs Docker. Cette question a commencé à être posée en 2013 dans l'article «Docker peut désormais s'exécuter dans Docker«.

En bref, il vous suffit d'installer Docker lui-même dans un conteneur fonctionnel et de monter le fichier /var/run/docker.sock.

Voici un exemple de Dockerfile qui s'est avéré pour 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

Ainsi, nous avons un conteneur Docker capable d'exécuter des commandes Docker sur la machine hôte.

Configuration de la construction

Il n'y a pas si longtemps, Jenkins a eu l'occasion de décrire ses règles en utilisant Pipeline syntaxe, ce qui permet de modifier assez facilement le script de construction et de le stocker dans le référentiel.

Mettons donc un Dockerfile spécial dans le référentiel lui-même, qui contiendra toutes les bibliothèques nécessaires à la construction. De cette façon, le développeur peut lui-même préparer un environnement reproductible et n'aura pas à demander à OPS d'installer une version spécifique de Node.JS sur l'hôte.

FROM node:12.10.0-alpine

RUN npm install yarn -g

Cette image de build convient à la plupart des applications Node.JS. Que se passe-t-il si, par exemple, vous avez besoin d'une image pour un projet JVM avec un scanner Sonar inclus ? Vous êtes libre de choisir les composants dont vous avez besoin pour l’assemblage.

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/

Nous avons décrit l'environnement d'assemblage, mais qu'est-ce que Jenkins a à voir avec cela ? Et les agents Jenkins peuvent travailler avec de telles images Docker et les créer en interne.

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

Directive agent utilise la propriété dockeroù vous pouvez préciser :

  • le nom du conteneur d'assemblage selon votre politique de dénomination ;
  • arguments nécessaires pour exécuter le conteneur de construction, où dans notre cas, nous montons le répertoire courant en tant que répertoire à l'intérieur du conteneur.

Et déjà dans les étapes de construction, nous indiquons les commandes à exécuter dans l'agent de construction Docker. Cela peut être n'importe quoi, donc je lance également le déploiement d'applications en utilisant ansible.

Ci-dessous, je souhaite montrer un fichier Jenkins générique qu'une simple application Node.JS peut créer.

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 qui s'est passé?

Grâce à cette méthode, nous avons résolu les problèmes suivants :

  • le temps de configuration de l'assemblage de l'environnement est réduit à 10 à 15 minutes par projet ;
  • un environnement de création d'applications entièrement reproductible, puisque vous pouvez le créer de cette façon sur votre ordinateur local ;
  • il n'y a aucun problème de conflits entre les différentes versions des outils d'assemblage ;
  • toujours un espace de travail propre et non obstrué.

La solution elle-même est simple et évidente et vous permet de bénéficier de certains avantages. Oui, le seuil d'entrée a un peu augmenté par rapport aux commandes simples pour les assemblys, mais il existe désormais une garantie qu'il sera toujours construit et le développeur lui-même peut choisir tout ce qui est nécessaire à son processus de construction.

Vous pouvez également utiliser l'image que j'ai collectée Jenkins + Docker. Toutes les sources sont ouvertes et situées à rmuhamedgaliev/jenkins_docker.

Lors de la rédaction de cet article, une discussion a eu lieu sur l'utilisation d'agents sur des serveurs distants afin de ne pas charger le nœud maître à l'aide d'un plugin plugin docker. Mais j'en parlerai à l'avenir.

Source: habr.com

Ajouter un commentaire