
Su Habr ci sono molti articoli su Jenkins, ma pochi descrivono un esempio pratico di funzionamento di Jenkins e degli agenti Docker. Tutti gli strumenti di build più popolari come , , , e altri possono compilarli all'interno di contenitori. Ma come si comporta Jenkins?
Oggi c'è una soluzione al problema: Jenkins 2 sa lavorare benissimo con gli . In questo articolo voglio condividere la mia esperienza e mostrarti come puoi farlo tu stesso.
Perché mi sono occupato di risolvere questo problema?
Poiché nella nostra azienda utilizziamo molteplici tecnologie, la macchina di build deve ospitare diverse versioni di Node.JS, Gradle, Ruby, JDK e altro. Ma spesso non si possono evitare conflitti di versione. Sì, avresti ragione a dire che esistono diversi gestori di versioni come nvm, rvm, ma non tutto è così semplice con loro e queste soluzioni presentano problemi:
- un grande volume di runtime che gli sviluppatori dimenticano di pulire;
- ci sono conflitti tra diverse versioni dello stesso runtime;
- ogni sviluppatore ha bisogno di un diverso insieme di componenti.
Ci sono altri problemi, ma preferisco raccontarti della soluzione.
Jenkins in Docker
Poiché Docker si è ormai ben radicato nel campo dello sviluppo, quasi tutto può essere eseguito utilizzando Docker. La mia soluzione è che Jenkins fosse in Docker e potesse eseguire altri contenitori Docker. Questa questione è stata sollevata per la prima volta nel 2013 in un articolo "«.
In breve, è necessario installare Docker stesso nel contenitore di lavoro e montare il file /var/run/docker.sock.
Ecco un esempio di Dockerfile che è stato creato 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 jenkinsCosì abbiamo ottenuto un contenitore Docker che può eseguire comandi Docker sulla macchina host.
Configurazione della build
Non molto tempo fa Jenkins ha ricevuto la possibilità di descrivere le proprie regole utilizzando una sintassi che consente di modificare facilmente lo script di build e di conservarlo nel repository.
Quindi, posizioniamo un Dockerfile speciale all'interno del repository, che conterrà tutte le librerie necessarie per la build. In questo modo, lo sviluppatore può preparare un ambiente riproducibile senza dover chiedere a OPS di installare una versione specifica di Node.JS sull'host.
FROM node:12.10.0-alpine
RUN npm install yarn -gQuesta immagine di build è adatta per la maggior parte delle applicazioni Node.JS. E se, ad esempio, avessi bisogno di un'immagine per un progetto JVM con incluso un scanner Sonar? Puoi scegliere autonomamente i componenti necessari per la build.
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 build, ma che c'entra Jenkins? Gli agenti di Jenkins possono lavorare con queste immagini Docker e condurre il processo di build al loro interno.
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à docker, dove puoi specificare:
- il nome del container di build secondo la tua politica di denominazione;
- gli argomenti necessari per avviare il container di build, dove nel nostro caso montiamo la directory corrente come directory all'interno del container.
E già nei passaggi di build specifichiamo quali comandi eseguire all'interno dell'agente Docker di build. Può essere qualsiasi cosa, in questo modo effettuo anche il deploy delle applicazioni utilizzando Ansible.
Di seguito voglio mostrare un Jenkinsfile generale che può costruire 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()
}
}
}Cosa ne è uscito?
Grazie a questo approccio abbiamo risolto i seguenti problemi:
- il tempo di configurazione dell'ambiente di build si riduce a 10-15 minuti per progetto;
- un ambiente di build dell'applicazione completamente ripetibile, poiché può essere costruito anche sul computer locale;
- nessun problema con conflitti tra diverse versioni degli strumenti di build;
- workspace sempre pulito, che non si intasa.
La soluzione in sé è semplice e ovvia e offre solo vantaggi. Sì, la soglia di ingresso è leggermente aumentata rispetto ai comandi semplici per le build, ma ora c'è la garanzia che verrà sempre eseguita e lo sviluppatore può scegliere tutto ciò che è necessario per il suo processo di build.
Puoi anche utilizzare l'immagine che ho creato. . Tutti i sorgenti sono aperti e disponibili su .
Durante la scrittura dell'articolo, è emersa una discussione sull'uso degli agenti su server remoti, per non sovraccaricare il nodo master tramite il plugin . Ma di questo parlerò in futuro.
Fonte: habr.com
