1. 持续集成
  2. 词汇表
持续集成 / 构建节点类型 / 默认节点环境

默认节点环境

功能介绍

构建任务由构建节点执行,而构建环境指的便是构建节点中内置的系统底层环境,预装了开发语言 SDK、命令行工具等服务。

构建环境有以下两类:

若开发项目对运行环境有特定要求,如 swift 项目需要在 macOS 环境下运行,可以参考自定义构建节点自行接入构建节点。

默认环境

在构建计划的开始环节中选择构建环境。

对应的 Jenkinsfileagent any

pipeline {
  agent any
  stages  {
    stage("检出") {...}
    stage("检查代码规范") {...}
  }
}

「CODING 云主机」为 Ubuntu 系统,预装了以下 SDK 和命令行工具:

SDK 命令行工具
android-sdk: 26.1.1 bundler: 1.17.2
build-essential cmake: 3.5.1
dotnet-core: 2.2 composer:1.10.8
elixir: 1.8.1 coscmd:1.8.5.36
erlang: Erlang/OTP 21 docker-compose: 1.26.0
go: 1.14.4 docker:20.10.6
java: 1.8.0_191 git-lfs: 2.7.2
nodejs: 10 git:2.28.0
php: 8.0、7.4、7.3 gradle: 4.10.2
python3/pip3: 3.9、3.8、3.7 helm: 2.13.1
python: 2.7.12 jq: 1.5-1-a5b5cbe
ruby: 2.6.0 kubectl: 1.18.4
maven: 3.6.3
mercurial: 3.7.3
pigz: 2.3.1
rancher: 2.2.0
rvm: 1.29.7
sshpass: 1.05
svn: 1.9.3
tccli: 3.0.67.1
vsftpd: 3.0.3
yarn: 1.15.2
axcl: 2.5

⚠️ 预装的软件版本有限且定期升级,而各个项目所需要的版本可能不同。

自定义版本

在持续集成中可自行下载安装软件的各种版本,如果官网下载较慢,我们亦提供了镜像服务以供下载。如需增加制品,欢迎提交至开源项目

Go

stage('Go') {
  steps {
    // 建议设置「缓存目录」 /root/.cache/downloads
    sh 'mkdir -p /root/.cache/downloads'
    dir ('/root/.cache/downloads') {
      sh 'wget -nc "https://coding-public-generic.pkg.coding.net/public/downloads/go-linux-amd64.tar.gz?version=1.17.1" -O go-linux-amd64-1.17.1.tar.gz | true'
      sh 'tar -zxvf go-linux-amd64-1.17.1.tar.gz -C /root/programs'
    }
    sh 'go version'
  }
}

Helm

stage('Helm') {
  steps {
    sh 'mkdir -p /root/.cache/downloads'
    dir ('/root/.cache/downloads') {
      sh 'wget -nc "https://coding-public-generic.pkg.coding.net/public/downloads/helm-linux-amd64.tar.gz?version=v3.6.3" -O helm-linux-amd64-v3.6.3.tar.gz | true'
      sh "tar -zxvf helm-linux-amd64-v3.6.3.tar.gz -C \$HELM_BIN linux-amd64/helm --strip-components 1"
    }
    sh 'helm version'
  }
}

kubectl

stage('kubectl') {
  steps {
    sh 'mkdir -p /root/.cache/downloads'
    dir ('/root/.cache/downloads') {
      sh 'wget -nc "https://coding-public-generic.pkg.coding.net/public/downloads/kubectl-linux-amd64?version=v1.22.1" -O kubectl-linux-amd64-v1.22.1 | true'
      sh 'cp kubectl-linux-amd64-v1.22.1 /usr/local/bin/kubectl'
    }
    sh 'chmod +x /usr/local/bin/kubectl'
    sh 'kubectl version --client'
  }
}

Node.js

stage('Node.js') {
  steps {
    sh 'curl -fsSL https://deb.nodesource.com/setup_14.x | bash -'
    // sh 'curl -fsSL https://deb.nodesource.com/setup_16.x | bash -'
    sh 'apt-get install -y nodejs'
    sh 'node -v'
  }
}

PHP

pipeline {
  agent {
    docker {
      reuseNode 'true'
      registryUrl 'https://coding-public-docker.pkg.coding.net'
      image 'public/docker/php:8.0'
      // image 'public/docker/php:7.4' 以及 7.3、7.2、7.1、5.6
      args '-v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker'
    }
  }
  stages {
    stage('安装依赖') {
      steps {
        // Possible values for ext-name:
        // bcmath bz2 calendar ctype curl dba dom enchant exif fileinfo filter ftp gd gettext gmp
        // hash iconv imap interbase intl json ldap mbstring mysqli oci8 odbc opcache pcntl pdo
        // pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell
        // readline recode reflection session shmop simplexml snmp soap sockets sodium spl standard
        // sysvmsg sysvsem sysvshm tidy tokenizer wddx xml xmlreader xmlrpc xmlwriter xsl zend_test zip
        sh 'apt-get update && apt-get install -y libbz2-dev'
        sh 'docker-php-ext-install bz2'
        sh 'php -i | grep bz2'
      }
    }
  }
}

Docker 环境

你可以通过以下方式使用 Docker 构建环境:

  • CODING 官方提供的镜像
  • 使用已托管至项目级制品库的 Docker 镜像
    适用于项目层级的标准构建环境,保障项目内镜像安全,方便管理,通过项目令牌您也可以拉取其他项目的镜像。
  • 使用指定 Registry 地址(默认为 Docker Hub)的 Docker 镜像
  • 使用 Dockerfile 脚本构建环境

CODING Docker 镜像

在【持续集成计划设置】->【流程配置】->【基础配置】->【图形化编辑器】中,选择 「使用 CODING 官方提供的 Docker 镜像」,比如 Node.js 14:

对应的 Jenkinsfile 参考:

pipeline {
  agent {
    docker {
      reuseNode 'true'
      registryUrl 'https://coding-public-docker.pkg.coding.net'
      image 'public/docker/nodejs:14'
    }
  }
  stages {
    stage('Test') {
      steps {
        sh 'node --version'
      }
    }
  }
}

项目制品库 Docker 镜像

点击选择使用已托管至制品仓库中的 Docker 镜像。

对应的 Jenkinsfile

pipeline {
  agent {
    docker {
      reuseNode 'true'
      registryUrl 'https://codes-farm-docker.pkg.coding.net'
      registryCredentialsId "${env.DOCKER_REGISTRY_CREDENTIALS_ID}"
      image 'coding-workshop/release/workshop-web-app:1.2.3'
    }
  }
}

如需参考如何推送自定义构建环境镜像到制品库并将其作为持续集成构建环境,请阅读参考

⚠️ env.CODING_ARTIFACTS_CREDENTIALS_ID 变量只可用于本项目的制品库,而跨项目使用制品库需按照下列步骤进行操作:

  1. 在制品库所在的项目中创建「项目令牌」,获得用户名和密码;
  2. 在持续集成所在的项目中录入「项目凭据」,选择「用户名+密码」类型,并授权给持续集成;
  3. 在持续集成中添加环境变量 DOCKER_CREDENTIALS_ID,取值选用「项目凭据」,上方的代码也对应改成 registryCredentialsId env.DOCKER_CREDENTIALS_ID 即可。

指定地址的 Docker 镜像

其中,「Docker 镜像」为必填项,需要填入您的镜像名称。「Registry 地址」需填写的格式为不带路径的 URL 地址,例如 https://codes-farm-docker.pkg.coding.net 而不是 https://codes-farm-docker.pkg.coding.net/laravel-demo/laravel-docker/

若拉取私有镜像,需录入凭据后填写 「Registry 认证凭据 ID」。

对应的 Jenkinsfile

pipeline {
  agent {
    docker {
      image 'node:14-alpine'
      reuseNode 'true'
    }
  }
  stages {
    stage('Test') {
      steps {
        sh 'node --version'
      }
    }
  }
}

Dockerfile 构建环境

若项目已经使用 Docker,建议将 Dockerfile 提交到代码库,用它作为持续集成构建环境。Dockerfile 示例代码:

FROM php:8.0-apache

RUN apt-get update \
  && apt-get install -y unzip

Jenkinsfile

pipeline {
  agent any
  stages {
    stage('Checkout') {
      steps {
        checkout([
          $class: 'GitSCM', 
          branches: [[name: env.GIT_BUILD_REF]], 
          userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]
        ])
      }
    }
    stage('Use Docker') {
      agent {
        dockerfile {
          filename 'Dockerfile' // 可选,自定义 Dockerfile 文件名
          dir 'build' // 可选,Dockerfile 所在目录
          additionalBuildArgs  '--build-arg version=1.0.2' // 可选,docker build 自定义参数
        }
      }
      stages {
        stage('Test') {
          steps {
            sh 'php -v'
            sh 'unzip -v'
          }
        }
      }
    }
  }
}

若构建次数频繁,而不想将时间浪费在 docker build 过程上,那么可以通过使用 Jenkins Dockerfile 保存镜像用于下次构建,从而节省大量时间,详情请点击了解

在阶段中使用 Docker

Jenkinsfile 参考:

pipeline {
  agent none
  stages {
    stage('Back-end') {
      agent {
        docker {
          image 'maven:3-alpine'
          reuseNode 'true'
        }
      }
      steps {
        sh 'mvn --version'
      }
    }
    stage('Front-end') {
      agent {
        docker {
          image 'node:14-alpine'
          reuseNode 'true'
        }
      }
      steps {
        sh 'node --version'
      }
    }
  }
}

多个 Docker 后台

自动化测试往往需要临时的基础设施(比如 MySQL、Redis、Elasticsearch)。那么创建一个桥接网络,在其中启动多个 Docker 后台,测试完毕自动删除。

node {
  stage("检出") {
    checkout([
      $class: 'GitSCM',
      branches: [[name: GIT_BUILD_REF]],
      userRemoteConfigs: [[
        url: GIT_REPO_URL,
        credentialsId: CREDENTIALS_ID
    ]]])
  }
  stage('准备数据库') {
    sh 'docker network create bridge1'
    sh(script:'docker run --net bridge1 --name mysql -d -e "MYSQL_ROOT_PASSWORD=my-secret-pw" -e "MYSQL_DATABASE=test_db" mysql:5.7', returnStdout: true)
    sh(script:'docker run --net bridge1 --name redis -d redis:5', returnStdout: true)
  }
  docker.image('ecoding/php:8.0').inside("--net bridge1 -v \"${env.WORKSPACE}:/root/code\" -e 'APP_ENV=testing' -e 'DB_DATABASE=test_db'" +
      " -e 'DB_USERNAME=root' -e 'DB_PASSWORD=my-secret-pw' -e 'DB_HOST=mysql' -e 'REDIS_HOST=redis'" +
      " -e 'APP_KEY=base64:tbgOBtYci7i7cdx5RiFE3KZzUkRtJfbU3lbj5uPdL8U='") {
    sh 'composer install'

    stage('单元测试') {
      sh 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-html storage/reports/tests/ --log-junit storage/test-results/junit.xml --coverage-text tests/'
      junit 'storage/test-results/junit.xml'
      codingHtmlReport(name: '测试覆盖率报告', path: 'storage/reports/tests/')
    }
  }
}

根节点工作空间

将自定义 Docker 用作构建环境时,可以选择是否使用根节点的工作空间。勾选该选项后,当前阶段的 Docker 容器会和流水线在同一台构建节点中运行,当前阶段在运行时便可以获取流水线工作空间下根目录保存的所有文件。

对应的 Jenkinsfile 参数为 reuseNode ,类型:Boolean,默认为 false:

pipeline {
  agent {
    docker {
      registryUrl 'https://coding-public-docker.pkg.coding.net'
      image 'public/docker/android:29'
    }
  }
  stages {
    // 代码被检出到 pipeline agent 的工作空间根目录下
    stage('检出代码') {
      steps {
        checkout([
          $class: 'GitSCM', 
          branches: [[name: env.GIT_BUILD_REF]], 
          userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]
        ])
      }
    }
    stage('单元测试') {
      agent {
        dockerfile {
          // 默认在当前节点工作空间根目录下找名为 「Dockerfile」的文件构建环境
          filename 'Dockerfile'
          // 如果 reuseNode 为 false,则无法找到之前检出到 pipeline agent 的工作空间根目录下的 Dockerfile
          reuseNode true
        }
      }
      steps {
        sh 'npm run test:ci'
        junit '*.xml'

      }
    }
  }
}

执行 Docker 命令

在 Jenkins Docker 环境中执行 docker 命令时,需要挂载外部虚拟机的 docker socket,否则会报错:docker: command not found

pipeline {
  agent {
    docker {
      image 'ecoding/php:8.0'
      reuseNode 'true'
      // 挂载外部虚拟机的 docker socket
      args '-v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker'
    }
  }
  stages {
    stage('自定义阶段') {
      steps {
        sh 'php -v'
      }
    }
    stage('构建 Docker 镜像') {
      steps {
        sh 'docker -v'
        script {
          docker.withRegistry("https://${env.CCI_CURRENT_TEAM}-docker.pkg.coding.net", "${env.CODING_ARTIFACTS_CREDENTIALS_ID}") {
            //docker.build("foo:bar").push()
          }
        }
      }
    }
  }
}

如果你希望在自定义构建节点中运行 Docker 命令,请执行以下操作:

  1. 在自有服务器上安装 Java、Docker;
  2. 接入 CODING 时请勿勾选「使用 Docker 运行构建节点」。

参考资料

Jenkins 官方文档——在流水线中使用 Docker 的 agent 语法说明

上一篇构建节点类型
最近更新
感谢反馈有用
感谢反馈没用

在阅读中是否遇到以下问题?

您希望我们如何改进?