如果您需要许多不同的环境,如何在 Jenkins 中收集项目

如果您需要许多不同的环境,如何在 Jenkins 中收集项目

Habré 上有很多关于 Jenkins 的文章,但很少有描述 Jenkins 和 docker 代理如何工作的示例。 所有流行的项目构建工具,例如 无人机网, 位桶管道, GitLab, GitHub 操作 和其他人,可以将所有东西收集到容器中。 但是詹金斯呢?

今天这个问题有了解决方案:Jenkins 2 非常擅长与 Docker 代理。 在这篇文章中,我想分享我的经验,并向您展示如何自己做到这一点。

我为什么开始解决这个问题?

既然我们在公司 香橼 因为我们使用许多不同的技术,所以我们必须在组装机上保留不同版本的 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

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 项目的映像,其中包含声纳扫描仪,该怎么办? 您可以自由选择组装所需的组件。

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 启动应用程序部署。

下面我想展示一个简单的 Node.JS 应用程序可以构建的通用 Jenkinsfile。

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 分钟;
  • 完全可重复的应用程序构建环境,因为您可以在本地计算机上以这种方式构建它;
  • 不存在不同版本组装工具冲突的问题;
  • 始终保持干净、不会堵塞的工作空间。

该解决方案本身简单明了,并且可以让您获得一些优势。 是的,与程序集的简单命令相比,入门门槛有所提高,但现在可以保证它将始终被构建,并且开发人员自己可以选择其构建过程所需的一切。

您也可以使用我收集的图片 詹金斯+码头工人。 所有来源都是开放的,位于 rmuhamedgaliev/jenkins_docker.

在撰写本文时,出现了关于在远程服务器上使用代理以避免使用插件加载主节点的讨论 docker-插件。 但我以后会谈到这个问题。

来源: habr.com

添加评论