
Habré上有很多关于Jenkins的文章,但是很少描述Jenkins和docker agent的工作示例。 所有流行的项目构建工具(例如Drone.io , Bitbucket Pipeline , GitLab , GitHub action等)都可以将所有内容收集在容器中。 但是詹金斯呢?
今天,有个解决方案:Jenkins 2 擅长使用Docker代理 。 在这篇文章中,我想分享经验并展示如何自己做。
为什么我要解决这个问题?
由于我们在Citronium使用许多不同的技术,因此必须在组装机上保留不同版本的Node.JS,Gradle,Ruby,JDK和其他版本。 但通常无法避免版本冲突。 是的,如果您说有各种版本管理器(例如nvm,rvm),那将是对的,但并不是所有的版本管理器都能如此顺畅,并且这些解决方案都存在问题:
- 开发人员忘记清理的大量运行时;
- 同一运行时的不同版本之间存在冲突;
- 每个开发人员都需要不同的组件集。
还有其他问题,但是让我更好地告诉您解决方案。
詹金斯在Docker中
由于Docker现在已经扎根于开发行业,因此几乎所有东西都可以使用Docker启动。 我的解决方案是让Jenkins位于Docker中并能够运行其他Docker容器。 这个问题开始于2013年在文章“ Docker现在可以在Docker中运行 ”中问过。
简而言之,只需将Docker安装在工作容器中并挂载/var/run/docker.sock
文件。
这是为Jenkins推出的Dockerfile示例。
FROM jenkins/jenkins:lts ARG DOCKER_COMPOSE_VERSION=1.25.0 USER root RUN apt-get update && \ apt-get upgrade -y && \ 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 && \ apt-get clean autoclean && apt-get autoremove && rm -rf /var/lib/{apt,dpkg,cache,log}/ RUN curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose RUN usermod -aG docker jenkins && gpasswd -a jenkins docker USER jenkins
因此,我们得到了一个Docker容器,可以在主机上执行Docker命令。
构建设置
不久前,Jenkins有了使用Pipeline语法描述其规则的机会,该语法使您可以简单地更改构建脚本并将其存储在存储库中。
因此,让我们在存储库本身中放入一个特殊的Dockerfile,它将包含构建库所需的所有库。 因此,开发人员本人可以准备一个可重复的环境,并且不需要OPS在主机上放置特定版本的Node.JS。
FROM node:12.10.0-alpine RUN npm install yarn -g
此构建映像适用于大多数Node.JS应用程序。 例如,如果您需要一个带有Sonar中包含的扫描仪的JVM项目的映像? 您可以自由选择需要构建的组件。
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分钟;
- 应用程序组装的完全可重复的环境,因为它也可以在本地计算机上组装;
- 与不同版本的组装工具没有冲突;
- 始终是干净的工作空间,不会被堵塞。
该解决方案本身简单明了,可以使您获得一些好处。 是的,与简单的构建命令相比,入门阈值有所提高,但是现在可以保证将始终收集该阈值,并且开发人员自己可以选择构建过程所需的所有内容。
您还可以使用我收集的Jenkins + Docker映像。 所有资源都是开放的,位于rmuhamedgaliev / jenkins_docker上 。
在撰写本文期间,讨论了有关在远程服务器上使用代理的问题,以免使用docker-plugin加载主节点。 但是我以后会谈。