
Na Habrze jest wiele artykułów o Jenkinsie, ale niewiele z nich opisuje przykład działania Jenkins i agentów Docker. Wszystkie popularne narzędzia do budowy projektów, takie jak , , , i inne, mogą kompilować wszystko w kontenerach. A co z Jenkins?
Dziś istnieje rozwiązanie problemu: Jenkins 2 doskonale potrafi pracować z W artykule chcę podzielić się doświadczeniem i pokazać, jak możesz to zrobić samodzielnie.
Dlaczego zająłem się rozwiązaniem tego problemu?
Ponieważ w naszej firmie używamy wielu różnych technologii, więc na maszynie do budowy musimy utrzymywać różne wersje Node.js, Gradle, Ruby, JDK i innych. Jednak często nie da się uniknąć konfliktów wersji. Tak, masz rację, jeśli powiesz, że są różne menedżery wersji, takie jak nvm, rvm, ale nie wszystko z nimi jest takie proste, a te rozwiązania mają swoje problemy:
- duża ilość środowisk uruchomieniowych, które deweloperzy zapominają czyścić;
- są konflikty między różnymi wersjami tych samych środowisk uruchomieniowych;
- każdemu deweloperowi potrzeba innego zestawu komponentów.
Są też inne problemy, ale lepiej opowiem o rozwiązaniu.
Jenkins w Dockerze
Ponieważ Docker jest już dobrze zakorzeniony w dziedzinie programowania, prawie wszystko można uruchomić za pomocą Dockera. Moim rozwiązaniem jest to, aby Jenkins był w Dockerze i mógł uruchamiać inne kontenery Docker. Te kwestie zaczęto poruszać już w 2013 roku w artykule „«.
Mówiąc krótko, trzeba tylko zainstalować Docker w kontenerze roboczym i zamontować plik. /var/run/docker.sock.
Oto przykład Dockerfile, który udało się stworzyć dla 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 jenkinsW ten sposób uzyskaliśmy kontener Docker, który może wykonywać polecenia Docker na maszynie gospodarczej.
Konfiguracja budowy
Niedawno Jenkins zyskał możliwość opisywania swoich reguł przy pomocy składni, co pozwala dość łatwo zmieniać skrypt budowy i przechowywać go w repozytorium.
Umieśćmy w repozytorium specjalny Dockerfile, który zawiera wszystkie niezbędne biblioteki do budowy. Dzięki temu deweloper może stworzyć powtarzalne środowisko i nie będzie musiał prosić OPS o zainstalowanie na hoście określonej wersji Node.JS.
FROM node:12.10.0-alpine
RUN npm install yarn -gTaki obraz budowy nadaje się do większości aplikacji Node.JS. A co jeśli potrzebujesz obrazu dla projektu JVM z wbudowanym skanerem Sonar? Możesz samodzielnie wybrać potrzebne komponenty do budowy.
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/
Opisaliśmy środowisko budowy, ale co ma z tym wspólnego Jenkins? Agenci Jenkinsa potrafią pracować z takimi obrazami Docker i przeprowadzać budowę w ich wnętrzu.
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"
}
}Dyrektywa agent używa właściwości docker, gdzie możesz określić:
- nazwę kontenera budowlanego zgodnie z twoją polityką nazewnictwa;
- argumenty potrzebne do uruchomienia kontenera budowlanego, gdzie w naszym przypadku montujemy bieżący katalog jako katalog wewnątrz kontenera.
A w krokach budowy wskazujemy, jakie komendy mają być wykonane wewnątrz agenta Docker do budowy. Może to być wszystko, w ten sposób również uruchamiam wdrożenie aplikacji z pomocą ansible.
Poniżej chciałbym przedstawić ogólny Jenkinsfile, który może zbudować prostą aplikację Node.JS.
def DOCKER_IMAGE_BRANCH = ""
def GIT_COMMIT_HASH = ""
pipeline {
options {
buildDiscarder(
logRotator(
artifactDaysToKeepStr: "",
artifactNumToKeepStr: "",
daysToKeepStr: "",
numToKeepStr: "10"
)
)
disableConcurrentBuilds()
}
agent any
stages {
stage("Przygotuj obraz do budowy") {
steps {
sh "docker build -f Dockerfile.build . -t project-build:${DOCKER_IMAGE_BRANCH}"
}
}
stage("Zbuduj 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()
}
}
}Co z tego wynikło?
Dzięki temu rozwiązaniu udało się nam rozwiązać następujące problemy:
- czas konfiguracji środowiska budowy wynosi 10–15 minut na projekt;
- pełne powtarzalne środowisko budowy aplikacji, ponieważ można to robić również na lokalnym komputerze;
- brak problemów z konfliktami różnych wersji narzędzi budowlanych;
- zawsze czysty workspace, który nie jest zaśmiecony.
Rozwiązanie jest proste i oczywiste oraz przynosi same korzyści. Tak, próg wejścia jest trochę wyższy w porównaniu do prostych poleceń budowlanych, ale teraz mamy gwarancję, że zawsze będzie budowane i programista sam może wybrać wszystko, co potrzebne do jego procesu budowy.
Możesz również skorzystać z utworzonego przeze mnie obrazu . Wszystkie źródła są otwarte i dostępne na .
W trakcie pisania artykułu wywiązała się dyskusja na temat używania agentów na zdalnych serwerach, aby nie obciążać głównej nodu za pomocą wtyczki . Ale o tym opowiem w przyszłości.
Źródło: habr.com
