
Su Habr ci sono molti articoli su Jenkins, ma pochi descrivono esempi di utilizzo di Jenkins e agenti Docker. Tutti gli strumenti di build popolari come , , , e altri, possono costruire tutto in contenitori. Ma come sta messo Jenkins?
Al giorno d'oggi esiste una soluzione al problema: Jenkins 2 sa lavorare magnificamente con . In questo articolo voglio condividere la mia esperienza e mostrare come puoi farlo tu stesso.
Perché mi sono occupato di risolvere questo problema?
Poiché nella nostra azienda utilizziamo molte tecnologie diverse, sulla macchina di build è necessario mantenere diverse versioni di Node.JS, Gradle, Ruby, JDK e altro. Ma spesso i conflitti di versione sono inevitabili. Sì, avrai ragione se dici che ci sono vari gestori di versioni come nvm, rvm, ma non tutto funziona senza intoppi con loro e queste soluzioni hanno problemi:
- grandi quantità di runtime che gli sviluppatori dimenticano di pulire;
- ci sono conflitti tra diverse versioni dello stesso runtime;
- ogni sviluppatore ha bisogno di un set diverso di componenti.
Ci sono anche altri problemi, ma lasciami raccontare la soluzione.
Jenkins in Docker
Poiché Docker è ormai ben radicato nel campo dello sviluppo, quasi tutto può essere eseguito tramite Docker. La mia soluzione è che Jenkins sia in Docker e possa avviare altri contenitori Docker. Questa questione è stata sollevata già nel 2013 in un articolo ‘«.
In sintesi, è necessario installare Docker all'interno del contenitore di lavoro e montare il file /var/run/docker.sock.
Ecco un esempio di Dockerfile 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 jenkinsIn questo modo 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 tramite sintassi, che consente di modificare abbastanza facilmente lo script di build e di archiviarlo nel repository.
Quindi, mettiamo nel repository stesso un apposito Dockerfile, che conterrà tutte le librerie necessarie per la build. In questo modo, lo sviluppatore può preparare un ambiente ripetibile 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, avete bisogno di un'immagine per un progetto JVM con all'interno Sonar scanner attivato? Potete scegliere i componenti necessari per la build come preferite.
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 tali immagini Docker e effettuare la build all'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 agente usa la proprietà docker, dove è possibile specificare:
- il nome del contenitore di build secondo la vostra politica di denominazione;
- gli argomenti necessari per eseguire il contenitore di build, dove nel nostro caso montiamo la directory corrente come directory all'interno del contenitore.
E già nei passi di build specifichiamo quali comandi eseguire all'interno dell'agente Docker di build. Può essere qualsiasi cosa, in questo modo eseguo 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("Prepara l'immagine di build") {
steps {
sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
}
}
stage("Costruisci il progetto") {
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 è uscito?
Grazie a questo metodo 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é si può costruire anche sul computer locale;
- nessun problema con i conflitti tra versioni diverse degli strumenti di build;
- workspace sempre pulito, che non si riempie.
Di per sé, la soluzione è semplice e ovvia e consente di ottenere solo vantaggi. Sì, la soglia di ingresso è leggermente aumentata rispetto ai semplici comandi di build, ma ora c'è la garanzia che verrà sempre costruito e lo sviluppatore può scegliere tutto ciò di cui ha bisogno per il suo processo di build.
Puoi anche utilizzare l'immagine che ho creato . Tutti i sorgenti sono aperti e si trovano su .
Durante la scrittura dell'articolo è emersa una discussione sull'uso di agenti su server remoti, per non sovraccaricare il nodo principale tramite il plugin . Ma di questo parlerò in futuro.
Fonte: habr.com
