Jenkins + gitlab 自动构建

环境信息

  • Jenkins jenkinsci/blueocean:2.346.3
  • GitLab Community Edition 13.9.6
  • Docker 19.03.15

本文档记录 GitLab 上面的代码更新时,使用 Jenkins 自动构建 Docker 镜像的过程。

配置过程

使用 docker 启动 Jenkins 容器

docker run -d -p 8080:8080 --name jenkins \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /data/JenkinsData_blueocean/:/var/jenkins_home/ \
-u root \
jenkinsci/blueocean

Jenkins 配置

以下分别记录使用 freestylePipeline 类型的构建镜像的配置过程

创建 freestyle 类型的 Item 构建镜像

源码管理(Source Code Management) 中配置 git 地址,并配置认证

默认情况下,在构建时,Jenkins 会先从配置的 Git 地址拉取代码到 Jenkins 目录: /var/jenkins_home/workspace/${PROJECT_NAME}

构建(Build)Add build step ,选择构建类型为 Execute shell,此处构建的示例项目代码结构如下,其中 Dockerfile 路径为 k8s/server/Dockerfile

.:
index.html k8s

./k8s:
server

./k8s/server:
Dockerfile

使用如下 shell 脚本

#!/bin/sh

DATA=`date +%Y%m%d%H%M`

DIR='.'

LOG=${DIR}/docker_build_result.log

DOCKER_REGISTRY='harbor.a.com'

DOCKER_REGISTRY_PROJECT='test'

PROJECT='test_project'
ENV='uat'

docker build -t ${PROJECT}-${ENV}-${Branch}:${DATA} -f k8s/server/Dockerfile ${DIR} | tee ${LOG}

docker tag ${PROJECT}-${ENV}-${Branch}:${DATA} ${DOCKER_REGISTRY}/${DOCKER_REGISTRY_PROJECT}/${PROJECT}-${ENV}-${Branch}:${DATA}

docker login -u admin -p Harbor12345 ${DOCKER_REGISTRY}

docker push ${DOCKER_REGISTRY}/${DOCKER_REGISTRY_PROJECT}/${PROJECT}-${ENV}-${Branch}:${DATA}

RESULT=`cat ${LOG} | tail -n 1`

grep "Successfully tagged " ${LOG}

exit $?

其中的 ${Branch} 来自 参数化的构建

使用 Jenkins Pipeline 构建镜像

创建 Pipeline 类型的工程

Advanced Project Options 中选择 Pipeline from SCM,并配置 Git 的 url 及认证信息。Script Path 默认为 Jenkinsfile(位于代码根目录)

Jenkinsfile 内容如下:

Jenkinsfile
pipeline {
agent any
environment {
PROJECT='test_admin'

HARBOR_CREDENTIALS = credentials('habor')
GIT_CREDENTIALS = credentials('git')

GIT_URL = "http://${GIT_CREDENTIALS_USR}:${GIT_CREDENTIALS_PSW}@git.wkctrlsys.com:18081/jiafeimao/api.git"

DATA="${sh(script: 'date +%Y%m%d%H%M', returnStdout:true)}"
LOG='./docker_build_result.log'

DOCKER_REGISTRY='harbor.my.com'
DOCKER_REGISTRY_PROJECT='test'

BRANCH = "${params.Branch}"

DIR = '.'

TAG = "${PROJECT}-${BRANCH}:${DATA}"
}

stages {
stage('CHECKOUT') {
steps {
// 清空 workspace
sh "rm -rf ${env.WORKSPACE}/*"
sh "rm -rf ${env.WORKSPACE}/.git"
sh "git clone -b ${BRANCH} ${GIT_URL} ."
}
}
stage('BUILD') {
steps {
sh 'docker build -t ${TAG} -f k8s/server/Dockerfile ${DIR} | tee ${LOG}'
}
}
stage('PUSH') {
steps {
sh 'docker tag ${TAG} ${DOCKER_REGISTRY}/${DOCKER_REGISTRY_PROJECT}/${TAG}'

sh 'docker login -u ${HARBOR_CREDENTIALS_USR} -p ${HARBOR_CREDENTIALS_PSW} ${DOCKER_REGISTRY}'

sh 'docker push ${DOCKER_REGISTRY}/${DOCKER_REGISTRY_PROJECT}/${TAG}'

}

}
}
}

常见错误

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

错误场景

使用 Docker 部署的 Jenkins,在构建 Docker 镜像时,Jenkins 中的 docker 为客户端,使用的 Server 端是宿主机的 Docker Daemon,默认情况下,docker 客户端是通过 unix:///var/run/docker.sock 连接 Docker 服务端,此文件在 Jenkins 容器中不能直接访问,所以导致出现上述错误。

解决思路

针对此种情况,需要让 docker 客户端可以正确的连接到 docker 服务端

解救方法

为 docker 客户端指定 docker 服务端,可以采取以下方法

  • 将宿主机的 /var/run/docker.sock 挂载到 Jenkins 容器
    docker run -d -p 8080:8080 --name jenkins -v /var/run/docker.sock:/var/run/docker.sock  jenkinsci/blueocean

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

错误场景

使用 Docker 部署的 Jenkins,默认情况下,容器中使用 jenkins 用户运行,无权限访问 /var/run/docker.sock,可以使用如下命令,在启动容器时使用 root 用户运行

docker run -d -p 8080:8080 --name jenkins \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /data/JenkinsData_blueocean/:/var/jenkins_home/ \
-u root \
jenkinsci/blueocean

WorkflowScript: 3: Invalid agent type “docker” specified. Must be one of [any, label, none]

错误原因

没有 docker 相关的插件导致,安装插件 Docker Pipeline