
Der er mange artikler om Jenkins på Habr, men sjældent beskrives et eksempel på, hvordan Jenkins og Docker-agenter fungerer. Alle populære projektbyggeværktøjer som , , , og andre kan samle alt i containere. Men hvad med Jenkins?
I dag er der en løsning på problemet: Jenkins 2 fungerer fremragende med . I denne artikel vil jeg dele mine erfaringer og vise, hvordan du kan gøre det selv.
Hvorfor begyndte jeg at løse dette problem?
Da vi i virksomheden bruger mange forskellige teknologier, er det nødvendigt for byggeværktøjet at have forskellige versioner af Node.JS, Gradle, Ruby, JDK og andre. Men oftest er der uundgåelige versionskonflikter. Ja, du har ret, hvis du siger, at der findes forskellige versionsadministrationsværktøjer som nvm, rvm, men det er ikke så glat med dem, og disse løsninger har deres problemer:
- et stort volumen af runtime-miljøer, som udviklerne glemmer at rydde op;
- der er konflikter mellem forskellige versioner af de samme runtime-miljøer;
- hver udvikler har brug for et forskelligt sæt af komponenter.
Der er også andre problemer, men lad mig hellere fortælle om løsningen.
Jenkins i Docker
Da Docker nu er godt etableret inden for udvikling, kan næsten alt køres ved hjælp af Docker. Min løsning er, at Jenkins skal køre i Docker og være i stand til at starte andre Docker-containere. Dette spørgsmål blev rejst allerede i 2013 i artiklen "«.
Kort sagt, er det nødvendigt at installere Docker i containeren og montere filen /var/run/docker.sock.
Her er et eksempel på Dockerfile, som vi har lavet til 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 jenkinsPå denne måde fik vi en Docker-container, der kan udføre Docker-kommandoer på værtsmaskinen.
Konfiguration af bygning
For nylig fik Jenkins muligheden for at beskrive sine regler ved hjælp af syntaks, som gør det relativt simpelt at ændre bygge-scriptet og opbevare det i et repository.
Lad os placere en særlig Dockerfile i selve depotet, som vil indeholde alle de nødvendige biblioteker til opbygning. På den måde kan udvikleren forberede et gentageligt miljø, og der er ikke behov for at anmode OPS om at installere en bestemt version af Node.JS på værten.
FROM node:12.10.0-alpine
RUN npm install yarn -gDenne byggeimage er passende til de fleste Node.JS-applikationer. Men hvis du for eksempel har brug for en image til et JVM-projekt med Sonar-scanneren inkluderet? Du er fri til at vælge de nødvendige komponenter til opbygning.
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/
Vi har beskrevet byggeomgivelserne, men hvad har Jenkins med det at gøre? Jenkins-agenter kan arbejde med sådanne Docker-images og udføre opbygning indeni.
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"
}
}Direktiv agent bruger egenskaben docker, hvor du kan angive:
- navnet på byggecontaineren i henhold til din navngivningspolitik;
- de nødvendige argumenter til at køre byggecontaineren, hvor vi i vores tilfælde monterer den nuværende mappe som en mappe inde i containeren.
Og i bygge-trinnene angiver vi, hvilke kommandoer der skal udføres inde i bygge-Docker-agenten. Det kan være hvad som helst, på den måde kan jeg også udføre deployment af applikationer ved hjælp af Ansible.
Her vil jeg vise et generelt Jenkinsfile, der kan samle en simpel Node.JS-applikation.
def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""
pipeline {
options {
buildDiscarder(
logRotator(
artifactDaysToKeepStr: "",
artifactNumToKeepStr: "",
daysToKeepStr: "",
numToKeepStr: "10"
)
)
disableConcurrentBuilds()
}
agent any
stages {
stage("Forbered build billede") {
steps {
sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
}
}
stage("Byg projekt") {
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()
}
}
}Hvad er resultatet?
Takket være denne metode har vi løst følgende problemer:
- tiden til at konfigurere build-omgivelser reduceres til 10-15 minutter pr. projekt;
- et helt reproducerbart bygget miljø for applikationen, da det også kan bygges på den lokale computer;
- der er ingen problemer med konflikter mellem forskellige versioner af build-værktøjer;
- altid et rent arbejdsrum, som ikke bliver fyldt op.
Selve løsningen er simpel og indlysende og giver kun fordele. Ja, indgangsbarrieren er en smule højere sammenlignet med simple build-kommandoer, men nu er der garanti for, at det altid vil blive bygget, og udvikleren kan selv vælge alt, hvad der er nødvendigt for hans build-proces.
Du kan også bruge det billede, jeg har samlet . Alle kilder er åbne og ligger på .
Under skrivningen af artiklen opstod der en diskussion om brugen af agenter på fjernservere for ikke at belaste master-noden ved hjælp af pluginet . Men det vil jeg fortælle om i fremtiden.
Kilde: habr.com
