过程简介
本文介绍在kubeSphere平台上,基于s2i(source-to-image)实现java代码持续集成并推送镜像至harbor仓库的过程。整个过程分为以下步骤:
- 在kubeSphere平台DevOps项目中创建项目
- 在项目中创建凭证
- 在项目中创建流水线
- 在流水线中编辑流水线
在流水线的编辑中,可以便捷流水线,也可以编辑Jenkinsfile。其中流水线内的代码逻辑如下:
- 在gitlab上下载需要构建的代码,放到src目录下
- 在gitlab上下载s2i工具的代码,用作构建时使用
- 登录dockerhub
- 拉取s2i需要使用的编译镜像(该镜像包括jdk、maven等)
- 使用s2i build命令(步骤2),对源代码(步骤1) 使用编译镜像(步骤4)进行构建,生成中间镜像
- 使用docker build命令,把中间镜像、运行时镜像(只包含运行的基础,没有maven等构建的内容,要小很多)分别作为参数传入到Dockerfile(在步骤2的源码中)中,进行最终镜像的构建。
- docker tag 对步骤6 按harbor地址重新tag.
- 推送到harbor。
创建项目
在项目中,创建gitlab和harbor凭证。
创建流水线,暂时可不选代码仓库,参数可增加,也可后续增加。
编辑参数,这里的参数,是运行时可以进行修改的,以便抽象复用内容固话到Jenkinsfile中,非公用的可以作为参数来进行手动填写。
效果如下:
编辑流水线
流水线中使用到的一些参数和文件说明:
AI_MODULE: 具体某个模块
BRANCH_NAME: 分支
s2i命令
s2i build [] [flags]
本案例对应如下:
./s2i_v1.1.14/s2i build ./src ${BUILDER_IMAGE}
A
I
M
O
D
U
L
E
−
t
m
p
:
{AI_MODULE}-tmp:
AIMODULE−tmp:TAG -e ARTIFACT_DIR=${AI_MODULE}-bootstrap --network=host
该命令的ARTIFACT_DIR参数是因为build_Image中需要,即指定具体target文件是谁,因为 该案例中 ./src文件中最终jar在xxx-bootstrap下,顾参数=${AI_MODULE}-bootstrap。 --network=host 指定builderImage中docker中网络使用host,与宿主机相同,否则build_Image中的maven地址等可能访问不到。
devops-ci-s2i.git:s2i工具的源码,包含s2i工具和一个Dockerfile文件。具体结构如下
- devops-ci-s2i
- Dockerfile
- README.md
- s2i_v1.1.14
- s2i
其中上s2i是官网下载可执行文件。Dockerfile 内容如下
##############
# 把 buildImage 编译好的临时镜像中的jar包拷贝到runtimeImage 中
# build 成新的 镜像
##############
ARG TMP_IMAGE
ARG RUNTIME_IMAGE
FROM ${TMP_IMAGE} as stage-temp
MAINTAINER comtoper@163.com
ARG RUNTIME_IMAGE
FROM ${RUNTIME_IMAGE}
# 把第一个 FROM 的镜像中的文件,拷贝到 第二个FROM 的镜像中
COPY --from=stage-temp /opt/app-root/app.jar /usr/local/s2i/app-root/
COPY --from=stage-temp /usr/local/s2i/run /usr/local/s2i/
WORKDIR /usr/local/s2i
CMD ["/usr/local/s2i/run"]
# docker build --build-arg TMP_IMAGE="xxx:latest" --build-arg RUNTIME_IMAGE="xxx/java-8-runtime:latest" -t newImageName:0.0.1 .
流水线代码:
pipeline {
agent {
node {
label 'base'
}
}
stages {
stage('clone code') {
agent none
steps {
container('base') {
git(url: 'https://xxxx/xx/${AI_MODULE}.git', credentialsId: 'gitlab-secret', branch: '${BRANCH_NAME}', changelog: true, poll: false)
sh 'mkdir ../src'
sh 'mv ./* ./.[^.]* ../src'
sh 'echo "list src files -> " && ls -alrt ../src && echo "->"'
git(url: 'https://xxxx/xx/devops-ci-s2i.git', credentialsId: 'gitlab-secret', branch: 'master', changelog: true, poll: false)
sh 'mv ../src ./'
sh 'echo "list all files -> " && ls -alrt && echo "->"'
sh 'chmod 777 ./s2i_v1.1.14/s2i'
sh './s2i_v1.1.14/s2i version'
}
}
}
//${A} 等同于 $A
stage('build & push') {
agent none
steps {
container('base') {
withCredentials([usernamePassword(credentialsId : "$DOCKER_CREDENTIAL_ID" ,passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,)]) {
sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh 'docker pull ${BUILDER_IMAGE}'
sh './s2i_v1.1.14/s2i build ./src ${BUILDER_IMAGE} ${AI_MODULE}-tmp:$TAG -e ARTIFACT_DIR=${AI_MODULE}-bootstrap --network=host'
sh 'docker build --build-arg TMP_IMAGE=${AI_MODULE}-tmp:$TAG --build-arg RUNTIME_IMAGE=${RUNTIME_IMAGE} -f ./Dockerfile -t ${AI_MODULE}:${TAG} .'
sh 'docker tag $AI_MODULE:$TAG $REGISTRY/$DOCKERHUB_NAMESPACE/ai-$AI_MODULE:$TAG'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/ai-$AI_MODULE:$TAG'
}
}
}
}
}
environment {
DOCKER_CREDENTIAL_ID = 'harbor-secret'
KUBECONFIG_CREDENTIAL_ID = 'kubeconfig'
REGISTRY = 'xxxx'
DOCKERHUB_NAMESPACE = 'xxxx'
TAG = '0.0.1'
}
parameters {
string(name: 'BRANCH_NAME', defaultValue: 'master', description: '')
}
}