gitlab-ci java项目maven
Gitlab是企业常用的代码托管平台。
除了管理代码外,Gitlab还可以做持续集成和持续发布,这一点就需要依赖Gitlab-CI/CD的功能了。
首先要想使用该功能,就需要先安装gitlab-runner。gitlab-runner的下载 可以看这里
gitlab-runner的注册可以看这里。gitlab-runner 就是指某一台服务器(或docker容器,或k8s的节点)用来跑ci任务,当某台服务器安装了gitlab-runner,那么他就是gitlab-runner了。比如说,我们的仓库里有java后端项目 和vue的前端项目,那么我们就可以搞两台服务器跑ci任务,一台跑maven的,一台跑vue的
这里主要注意的两点就是
1.gitlab-runner Executor的选择,一般选择 Docker executor 或者 Kubernetes executor,选择Kubernetes executor 可以参照
2.runner 的TAG 设置(这个设置在gitlab上进行设置)
这里TAG设置,不能为纯数字,否则会提示.gitlab-ci.yml 文件语法错误(这一点需要注意) ,建议TAG的名字可以设置为构建的名称和ip。如果我这台机器 是跑maven的,服务器ip尾数为151,因此该Runner可以设置为maven-151。同样的,如果机器够多 同类型得也可以多搞几个,这样可以并发构建了。
本篇选择的是 Docker executor 。
安装完gitlab-runner 。可以查看gitlab-runner的配置文件。
[root@app01 ~]# cat /etc/gitlab-runner/config.toml
concurrent = 1 check_interval = 0 [[runners]] "name = "jie #这个url 是git的url url = "http://127.0.65.51:90/" #这个url是下载代码的url,如果发现无法下载代码,就手手动添加这个配置 clone_url = "http://127.0.65.51:90" # gitlab的token,这个是在注册时就配置加上的,该token是gitlab提供的 token = "bb21ebd38b0985b95fdada9024bb8e8" executor = "docker" [runners.docker] tls_verify = false image = "harbor.local/library/centos:centos7.5.1804" privileged = false disable_cache = false #这个配置很重要,我的这个runner是用来构建maven项目的,又因为使用的executor是docker,因此每次构建,都需要下载镜像,如果每次都去下载那会麻烦,因此做一个磁盘映射,/home/gitlab-runner/.m2 是宿主机的目录,该目录下 是所有的maven依赖 volumes = ["/cache","/home/gitlab-runner/.m2:/root/.m2"] shm_size = 0 [runners.cache]
上面的gitlab-runner配置文件中,有几个很重要的配置 一个是 clone_url 一个是 executor 最后一个是 volumes。
可以查看一下 我的 /home/gitlab-runner/.m2 路径下都是什么
其中repository文件夹下就是存放的各种jar依赖 ,而 settings.xml 则是 maven的配置文件,因此当我们在构建的时候就可以指定配置了。
下面就是.gitlab-ci.yml的配置信息了。
# 这个镜像很重要,因为我们是在docker内部使用docker命名,因此必须要能使用该镜像,最好runner上就存在该镜像 image: harbor.local/library/docker variables: #这个指的是生成的docker镜像放在那里,当然选择放在宿主机上了,此处需要注意,如果runner机器跟要放docker的机器不一样的话,需要做互信 DOCKER_HOST: tcp://172.98.60.152:2375 DOCKER_DRIVER: overlay2 #指定maven本地仓库地址 MAVEN_OPTS: "-Dmaven.repo.local=/root/.m2/repository" # 定义build shell BUILD_SHELL: "mvn clean package -Dmaven.test.skip=true $MAVEN_OPTS --settings=/root/.m2/settings.xml" stages: - package - build - test - deploy job-package: stage: package image: harbor.local/library/maven:3.6.3-ibmjava-8-alpine tags: #注意这里的tag,如果是纯数字,可能回报语法异常 - runner-151 script: - echo $CI_COMMIT_MESSAGE - echo `mvn --version` - echo $BUILD_SHELL - $BUILD_SHELL # 由于下一个job我们要使用该job打好的jar文件,因此加入artifacts artifacts: paths: - node-a1/target/*.jar - node-a2/target/*.jar - node-b1/target/*.jar - node-b2/target/*.jar job-build: stage: build image: harbor.local/library/docker dependencies: - job-package tags: #注意这里的tag,如果是纯数字,可能回报语法异常 - runner-151 script: #打印git提交信息 - echo $CI_COMMIT_MESSAGE - echo "###################" # 注意下面这一段script ,他是多行的。这里面做的事,就是判断提交信息是什么,然后选择性的就行ci。在docker build的时候 加入了一个参数DOCKER_JAVA_FILE_PATH,这是一个在Dockerfile中定义的一个参数 - if [ "$CI_COMMIT_MESSAGE" == "node-a1" ]; then pwd; ls; echo "======="; ls node-a1/target/ ; java_file_src=$(ls node-a1/target/ | sed "s:^:`pwd`/:"); echo $java_file_src;
# 这里的node-a1/target/*.jar 就是上一个job中定义的 docker build --build-arg DOCKER_JAVA_FILE_PATH=node-a1/target/*.jar -t node-a1 . ; echo 'build imgage as node-a1'; fi - if [ "$CI_COMMIT_MESSAGE" == "node-b1" ]; then pwd; ls; echo "======="; ls node-b1/target/ ; java_file_src=$(ls node-b1/target/ | sed "s:^:`pwd`/:") echo $java_file_src; docker build --build-arg DOCKER_JAVA_FILE_PATH=node-b1/target/*.jar -t node-b1 . ; echo 'build imgage as node-b1'; fi # after_script: # - docker rm jdk_temp job-test: stage: test tags: - runner-151 script: # https://blog.csdn.net/github_35631540/article/details/107864258 # 完整的提交消息 - echo $CI_COMMIT_MESSAGE # 构建项目的分支或标记名称 - echo $CI_COMMIT_REF_NAME # 提交分支名称。仅在建立分支时显示 - echo $CI_COMMIT_BRANCH # 提交标记名称。仅在构建标签时显示 - echo $CI_COMMIT_TAG
# 当前的Git CommitId
- ccho $CI_COMMIT_SHA
# 当前的Git CommitId 短ID 一般使用该值作为build镜像的TAG
- echo $CI_COMMIT_SHORT_SHA
# 上一次的commitid
- echo $CI_COMMIT_BEFORE_SHA
job-deploy:
stage: deploy
tags:
- runner-151
script:
# 发布
- echo $CI_COMMIT_MESSAGE
- echo "###################"
- if [ "$CI_COMMIT_MESSAGE" == "node-a1" ] ;then
docker stop nodea1 || true;
docker rm nodea1 || true;
echo 'start nodea1 image';
docker run -d -p 9090:9090 --name nodea1 -d node-a1:latest java -jar app.jar;
fi
- if [ "$CI_COMMIT_MESSAGE" == "node-b1" ] ;then
docker stop nodeb1 || true;
docker rm nodeb1 || true;
echo 'start nodeb1 image';
docker run -p 8080:8080 --name nodeb1 -d node-b1:latest java -jar app.jar;
fi
上面有几点是需要注意的。
1.是要自定义maven构建参数。指定 maven本地仓库地址,指定配置文件 settings.xml。这样可以在本地没有依赖的情况下,通过settings.xml中配置的中央仓库的地址去拉取依赖。
2.docker镜像。不要怀疑,镜像名字就是docker,要在docker中进行docker操作,需要docker in docker 也就是 dind
3.artifacts 的配置,在job中传递构建物,使用artifacts是比较方便的,这里需要注意的就是在任务中取artifacts时的路径问题。
4.Dockerfile 在构建镜像的时候我们使用if判断,因此说明Dockerfile中有一个是变量,具体导本例就是Dockerfile 中的ADD 操作,就是ADD什么到镜像里,因此我们需要在Dockerfile中设置变量,同时在docker build 是设置该变量的值。
5.关于部署。本例中runner 和实际应用服务器其实是一台服务器,因为我们可以直接进行部署,如果运行服务器是其他服务器,那么我们还需要将构建好的镜像进行推送,然后一个简单的方案是使用watchtower 来动态更新服务
一些常见问题:
运行 提示:This job does not have a trace
这个问题,花了很久时间才找到原因,之前是可用的,后来发现是docker hub的地址改变了,虽然本地有对应的镜像,但是runner服务器对应的docker hub中却没有镜像。因此解决方案就是将本地镜像push到docker hub中