На Хабре багато статей про Jenkins, але мало де описується приклад роботи Jenkins та докер агентів. Усі популярні інструменти складання проектів типу
На сьогоднішній день є вирішення проблеми: Jenkins 2 чудово вміє працювати з
Чому я зайнявся вирішенням цієї проблеми?
Тому що ми в компанії
- великий обсяг рантаймів, який розробники забувають чистити;
- є конфлікти між різними версіями одних рантаймів;
- кожному розробнику потрібний різний набір компонентів.
Є й інші проблеми, але давайте краще розповім про рішення.
Jenkins в Docker
Так як зараз Docker вже добре укоренився у сфері розробки, то майже все можна запустити за допомогою Docker. Моє ж рішення в тому, щоб Jenkins був у Docker та міг запускати інші Docker контейнери. Цим питанням стали задаватися ще 2013 року у статті «
Якщо коротко необхідно в робочий контейнер встановити сам Docker і вмонтувати файл /var/run/docker.sock
.
Ось приклад Dockerfile, який вийшов для 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 jenkins
Таким чином ми отримали Docker контейнер, який може виконувати Docker команди на хостовій машині.
Налаштування складання
Нещодавно Jenkins отримав можливість описувати свої правила за допомогою
Так давайте ж ми помістимо в самий репозиторій спеціальний Dockerfile, який міститиме в собі всі необхідні для складання бібліотеки. Таким чином, сам розробник може підготувати повторюване середовище і не потрібно буде OPS просити поставити на хост певну версію Node.JS.
FROM node:12.10.0-alpine
RUN npm install yarn -g
Такий складальний образ підходить для більшості програм Node.JS. А якщо вам, наприклад, потрібен образ для JVM проекту із включеним усередину Sonar сканером? Ви самі вільні вибирати потрібні для збирання компоненти.
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/
Ми описали складальне оточення, але до чого тут Jenkins? А Jenkins агенти вміють працювати з такими образами Docker і проводити збірку всередині.
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"
}
}
Директива agent
використовує властивість docker
, де ви можете вказати:
- ім'я складального контейнера відповідно до вашої політики неймінгу;
- аргументи необхідні для запуску конвеєра, де в нашому випадку ми монтуємо поточну директорію як директорію всередині контейнера.
А вже в кроках збирання ми вказуємо, які команди виконати всередині складального агента Docker. Це може все що завгодно, таким чином я також запускаю деплой додатків за допомогою ansible.
Нижче я хочу показати загальний Jenkinsfile, який може зібрати простий 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()
}
}
}
Що ж сталося?
Завдяки такому способу ми вирішили такі проблеми:
- час зміни складання оточення зводиться до 10 - 15 хвилин на проект;
- повністю повторюване оточення збірки програми, оскільки можна так збирати і локальному комп'ютері;
- немає проблем із конфліктами різних версій складальних інструментів;
- завжди чистий воркспейс, який не забивається.
Саме собою рішення просте і очевидне і дозволяє отримати одні плюси. Так, поріг входу трохи піднявся в порівнянні з простими командами для збірок, зате тепер є гарантія, що збиратиметься завжди і розробник сам може вибрати все, що необхідно для його процесу складання.
Також ви можете скористатися зібраним мною чином
Під час написання статті з'явилася дискусія щодо використання агентів на віддалених серверах, щоб не вантажити майстер ноду за допомогою плагіна
Джерело: habr.com