Comment construire des projets dans Jenkins, si vous avez besoin de beaucoup d'environnements différents

image


Il y a beaucoup d'articles sur Habré à propos de Jenkins, mais peu d'exemples du travail de Jenkins et d'agents dockers sont décrits. Tous les outils de construction de projets populaires comme Drone.io , Bitbucket Pipeline , GitLab , les actions GitHub et autres peuvent tout collecter dans des conteneurs. Mais qu'en est-il de Jenkins?


Aujourd'hui, il existe une solution au problème: Jenkins 2 est excellent pour travailler avec des agents Docker . Dans l'article, je veux partager mon expérience et montrer comment vous pouvez le faire vous-même.


Pourquoi ai-je résolu ce problème?


Étant donné que chez Citronium , 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 version ne peuvent pas être évités. Oui, vous aurez raison si vous dites qu'il existe différents gestionnaires de versions comme nvm, rvm, mais tout ne va pas si bien avec eux et ces solutions ont des problèmes:


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

Il y a d'autres problèmes, mais permettez-moi de vous parler mieux de la solution.


Jenkins dans Docker


Puisque Docker est maintenant bien ancré dans l'industrie du développement, presque tout peut être démarré à l'aide de Docker. Ma solution est que Jenkins soit dans Docker et puisse exécuter d'autres conteneurs Docker. Cette question a commencé à être posée en 2013 dans l'article " Docker peut désormais fonctionner dans Docker ".


Si en bref, il est simplement nécessaire d'installer Docker dans le conteneur de travail et de monter le fichier /var/run/docker.sock .


Voici un exemple Dockerfile qui est sorti pour Jenkins.


 FROM jenkins/jenkins:lts ARG DOCKER_COMPOSE_VERSION=1.25.0 USER root RUN apt-get update && \ apt-get upgrade -y && \ 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 && \ apt-get clean autoclean && apt-get autoremove && rm -rf /var/lib/{apt,dpkg,cache,log}/ RUN curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose RUN usermod -aG docker jenkins && gpasswd -a jenkins docker USER jenkins 

Ainsi, nous avons obtenu un conteneur Docker qui peut 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 la syntaxe Pipeline , qui vous permet de simplement changer 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 la bibliothèque. Ainsi, le développeur lui-même peut préparer un environnement reproductible et OPS n'aura pas besoin d'être invité à mettre 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. Et si, par exemple, vous avez besoin d'une image pour un projet JVM avec un scanner inclus à l'intérieur du Sonar? Vous êtes libre de choisir les composants dont vous avez besoin pour construire.


 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 de construction, mais qu'est-ce que Jenkins a à voir avec cela? Et les agents Jenkins peuvent travailler avec de telles images Docker et construire à l'intérieur.


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

La directive agent utilise la propriété docker , où vous pouvez spécifier:


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

jenkins


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


Ci-dessous, je veux montrer un fichier Jenkins générique qui peut créer une simple application 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() } } } 

Que s'est-il passé?


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


  • le temps de configuration de l'assemblage d'environnement est réduit à 10 - 15 minutes par projet;
  • environnement complètement reproductible de l'ensemble d'application, car il peut également être assemblé sur l'ordinateur local;
  • aucun conflit avec les différentes versions des outils d'assemblage;
  • toujours un espace de travail propre qui ne se bouche pas.

La solution elle-même est simple et évidente et vous permet d'obtenir certains avantages. Oui, le seuil d'entrée a légèrement augmenté par rapport aux commandes de build simples, mais maintenant il y a une garantie qu'il sera toujours collecté et le développeur lui-même peut choisir tout ce qui est nécessaire pour son processus de build.


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


Au cours de la rédaction de l'article, il y a eu une discussion sur l'utilisation d'agents sur des serveurs distants afin de ne pas charger le nœud maître à l'aide du plug-in docker . Mais j'en parlerai à l'avenir.

Source: https://habr.com/ru/post/fr481466/


All Articles