
Pe Habr există multe articole despre Jenkins, dar puține dintre ele descriu un exemplu de utilizare a agenților Docker pentru Jenkins. Toate instrumentele populare de construire a proiectelor, precum , , , și altele, pot să compileze totul în containere. Dar cum rămâne cu Jenkins?
În prezent, există o soluție pentru această problemă: Jenkins 2 știe să lucreze excelent cu . În acest articol vreau să împărtășesc experiența mea și să arăt cum puteți face acest lucru singuri.
De ce m-am apucat de soluționarea acestei probleme?
Având în vedere că, în compania , folosim numeroase tehnologii diferite, pe mașina de construire trebuie să avem diverse versiuni de Node.JS, Gradle, Ruby, JDK și altele. Totuși, conflictele de versiuni nu pot fi evitate. Da, veți avea dreptate dacă spuneți că există diferite manageri de versiuni, precum nvm, rvm, dar lucrurile nu sunt chiar atât de simple cu ei și aceste soluții au probleme:
- există un volum mare de runtime-uri pe care dezvoltatorii uită să le curețe;
- există conflicte între diferite versiuni ale acelorași runtime-uri;
- fiecare dezvoltator are nevoie de un set diferit de componente.
Există și alte probleme, dar mai bine să vă povestesc despre soluție.
Jenkins în Docker
Având în vedere că Docker este deja bine consacrat în domeniul dezvoltării, aproape totul poate fi pornit prin intermediul Docker. Soluția mea este ca Jenkins să fie în Docker și să poată rula alte containere Docker. Această întrebare a fost abordată încă din 2013 într-un articol intitulat „«.
Pe scurt, este necesar să instalați Docker în containerul de lucru și să montați fișierul /var/run/docker.sock.
Iată un exemplu de Dockerfile 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 jenkinsAstfel, am obținut un container Docker care poate executa comenzi Docker pe mașina gazdă.
Configurarea construirii
Nu cu mult timp în urmă, Jenkins a primit posibilitatea de a-și descrie regulile folosind sintaxei, ceea ce permite modificarea destul de simplă a scriptului de construire și stocarea acestuia în repository.
Așa că haideți să plasăm în repository un Dockerfile special, care va conține toate bibliotecile necesare pentru construcție. Astfel, dezvoltatorul poate pregăti un mediu replicabil și nu va trebui să ceară OPS-ului să instaleze o anumită versiune de Node.JS pe gazdă.
FROM node:12.10.0-alpine
RUN npm install yarn -gAceastă imagine de construire este potrivită pentru majoritatea aplicațiilor Node.JS. Și dacă, de exemplu, aveți nevoie de o imagine pentru un proiect JVM cu scannerul Sonar inclus? Sunteți liber să alegeți componentele necesare pentru construcție.
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 construcție, dar ce legătură are Jenkins? Agentele Jenkins pot lucra cu astfel de imagini Docker și pot efectua construcții în interior.
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"
}
}Directiva agent folosește proprietate docker, unde puteți specifica:
- numele containerului de construcție conform politicii dumneavoastră de denumire;
- argumentele necesare pentru a rula containerul de construcție, unde în cazul nostru montăm directorul curent ca director în interiorul containerului.
Și deja în pașii de construcție specifice care comenzi să fie executate în interiorul agentului Docker de construcție. Poate fi orice, astfel îl folosesc și pentru a rula deploy-ul aplicațiilor cu ajutorul ansible.
Mai jos vreau să arăt un Jenkinsfile general, care 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("Pregătește imaginea de construcție") {
steps {
sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
}
}
stage("Construiește proiectul") {
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 a rezultat?
Datorită acestei metode, am rezolvat următoarele probleme:
- timpul de configurare a mediu de construcție se reduce la 10 — 15 minute pe proiect;
- un mediu complet replicabil pentru construcția aplicației, deoarece se poate construi și pe computerul local;
- fără probleme cu conflictele între diferitele versiuni ale uneltelor de construcție;
- întotdeauna un spațiu de lucru curat, care nu se aglomerează.
În sine, soluția este simplă și evidentă și oferă doar avantaje. Da, pragul de intrare a crescut puțin comparativ cu comenzile simple pentru construcții, dar acum există garanția că va fi întotdeauna construit și dezvoltatorul poate alege tot ce este necesar pentru procesul său de construcție.
De asemenea, puteți folosi imaginea pe care am construit-o . Toate sursele sunt deschise și se află pe .
În timpul redactării articolului a apărut o discuție despre utilizarea agenților pe servere externe, pentru a nu încărca nodul principal prin pluginul . Dar despre asta voi povesti în viitor.
Sursa: habr.com
