在公司用了半年的 SpringCloud + Docker + Jenkins 的技术框架,现在流行持续集成,还没有抽点时间自己实际走一下全流程开发环境的搭建,正好赶上端午节,可以宅在出租屋里好好研究一下,特此记录一下实践过程中遇到的问题及解决方案。
搭建测试项目 请求接口
接口地址:/api/user-management/users
1 2 3 4 5 6 7 8 @GetMapping("/users") public Response<List<UserPo>> listUsers (@RequestParam int count) { Response<List<UserPo>> response = new Response <>(); response.setCode(0 ); response.setMessage("请求成功" ); response.setData(userService.listUsers(count)); return response; }
返回数据格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 { "code" : 0 , "message" : "请求成功" , "data" : [ { "no" : "U00-0" , "name" : "U-name0" , "level" : "高级用户" , "point" : 245 } , { "no" : "U00-1" , "name" : "U-name1" , "level" : "初级用户" , "point" : 238 } , { "no" : "U00-2" , "name" : "U-name2" , "level" : "初级用户" , "point" : 240 } ] }
Dockerfile 1 2 3 4 5 FROM openjdk:8-jdk-alpine VOLUME /tmp COPY springboot-demo.jar app.jar ENTRYPOINT ["java", "-jar", "/app.jar"] EXPOSE 8080
Jenkinsfile 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 pipeline { agent any stages { stage('Build') { steps { echo 'Building..' sh 'mvn clean && mvn package' sh 'cp target/springboot-demo.jar src/main/docker/springboot-demo.jar' echo 'Build completed.' } } stage("Image") { steps { echo 'Imaging..' sh 'cd src/main/docker && docker build --rm -t springboot-demo:v1 .' echo 'Image completed.' } } stage('Deploy') { steps { echo 'Deploying....' sh 'docker run -d -p 8082:8001 --name springboot-demo springboot-demo:v1' echo 'Deploy completed.' } } } }
Docker安装以及Dockerhub账户注册 注册Dockerhub账号,然后安装docker。
1 2 3 4 5 6 7 8 9 10 11 # 安装docker curl -sSL https://get.daocloud.io/docker | sh # 将用户加入docker组中 sudo gpasswd -a chenxii docker # 更新docker组 sudo grpnew docker # 登录docker,用docker id 登录而不是邮箱 # 不要直接 -p 登录,不安全 cat passwd.txt | docker login -u chenxii81 --password-stdin
Gitlab安装 本来想用VPS的,但是从docker启动gitlab之后总是几分钟就会Exit,应该是配置太低了,才512M内存,1核处理器。只能放到虚拟机弄了。
为了配置方便,用 Docker 安装 Gitlab:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 docker pull gitlab/gitlab-ce:latest docker run -d -p 443:443 -p 80:80 -p 222:22 --name gitlab gitlab/gitlab-ce:latest # e176b0d7d3d8775a293701d85029421eebf0ae6d013e79edb791c47df0e8c857 docker ps -a # 状态为 healthy之后就可以用宿主机ip进行访问了,Up 3 minutes (healthy) # 修改gitlab地址 # 打开文件 /etc/gitlab/gitlab.rb 文件并找到 # external_url 'GENERATED_EXTERNAL_URL' 这行,去掉注释,并按照下面的格式修改。 # 使用hosts里配置的域名,git提交会被redirect,最好用ip external_url 'http://gitlab.chenxii.com' 或者 external_url 'http://192.168.8.188' # 然后执行下面的命令使配置生效 sudo docker exec gitlab gitlab-ctl reconfigure # 修改完之后仓库的地址: git@gitlab.chenxii.com:gitlab-instance-8190bce8/Monitoring.git http://gitlab.chenxii.com/gitlab-instance-8190bce8/Monitoring.git # 将代码传到gitlab git remote add origin http://192.168.8.188/root/springboot-demo.git git add . git commit -m "init repo" git push -u origin --all git push -u origin --tags
初次登录需要重设密码,之后可以用root + 新密码登录。
Jenkins安装 使用Docker配置Jenkins
1 2 3 4 5 6 7 8 9 10 docker pull jenkins/jenkins:lts # Jenkins Docker镜像中没有Maven,所以将宿主机的Maven挂载到Docker容器 docker run -d -p 8081:8080 --name jenkins \ -v /opt/jdk/jdk1.8.0_181:/usr/lib/jvm/java-1.8-openjdk \ -v /opt/maven/maven-3.5.4:/usr/local/maven3 jenkins/jenkins:lts # 使用docker logs查看Jenkins初始化密码 docker logs container_id
安装推荐插件之后,创建用户进入Jenkins
安装Jenkins插件 maven 下载地址: apache-maven-3.8.1-bin.tar.gz
配置:
1 2 3 4 5 6 7 8 9 # 因为maven-3.8.1报错,换成了3.5.4版本 sudo mv ~/Downloads/apache-maven-3.5.4-bin.tar.gz /opt/maven sudo tar -zxvf apache-maven-3.5.4-bin.tar.gz cd apache-maven-3.5.4 sudo mv apache-maven-3.5.4/opt /maven-3.5.4 vim ~/.bashrc export MAVEN_HOME=/opt/maven/maven-3.5.4 export PATH=$PATH:$MAVEN_HOME/bin
配置Gitlab Key SSH Key 在 Gitlab 中 SSH Key 页面(http://192.168.8.188/-/profile/keys),将自己本地 ~/.ssh/id_rsa.pub 内容存进去,这样传代码不需要每次都输入密码。
Access Tokens 1、给Jenkins安装Publish Over SSH插件
2、Jenkins需要从Gitlab拉取代码,所以需要为Jenkins配置一个Access Tokens,类似:5nU3oGSxyZXsxHyuwekH,生成之后将其配置到 系统配置 > Publish over SSH > Key 保存。
Jenkins报错 mvn命令找不到 Jenkins报错 mvn 命令找不到,因为 Docker Jenkins里没有Maven。
1 2 3 4 5 + mvn clean /var/jenkins_home/workspace/springboot-demo_master@tmp/durable-c0a723ef/script.sh: 1: /var/jenkins_home/workspace/springboot-demo_master@tmp/durable-c0a723ef/script.sh: mvn: not found script returned exit code 127
配置如下:
在这里卡了很长时间,最后找到一个解决方案:Jenkins打包Maven项目找不到mvn解决办法script.sh: line 1: mvn: not found
启动命令中将宿主机上的maven路径挂在到Docker容器的 /usr/local/maven3目录下,然后在 系统配置 > 全局属性 下,将MAVEN_HOME追加到环境变量中,然后扫描流水线就可以下载依赖了。
1 2 # docker run中挂载宿主机maven到docker容器中 -v /opt/maven/maven-3.5.4:/usr/local/maven3 jenkins/jenkins:lts
还有一种挂载方式不需要重新运行镜像,直接给容器挂载新的目录:
修改 /var/run/docker/containerid/容器id/hostconfig.json 和 /var/run/docker/containerid/容器id/config.v2.json
参见:docker给已经启动容器添加挂载目录
键
值
MAVEN_HOME
/usr/local/maven3
PATH+EXTRA
$MAVEN_HOME/bin
docker命令找不到 解决方案:
给启动的Docker容器挂载宿主机的 docker 环境
参见:docker给已经启动容器添加挂载目录
/var/run/docker.sock: connect: permission denied 运行到 docker 构建镜像的时候提示权限不足,/var/run/docker.sock 只有 root 权限才能调用,可以将 jenkins 用户加到 docker 组下:
1 2 sudo gpasswd -a jenkins docker newgrp docker
但是这里docker是挂载了宿主机的docker目录,所以不存在docker组,直接将 /var/run/docker.sock 改成 777 权限:
1 2 3 docker exec -u 0 -it 容器id /bin/bash chmod -R 777 /var/run/docker.sock exit
再次构建:
20次的流水线扫描,上百次 Bing 搜索,终于成功看到了赏心悦目的绿色和接口返回值 🎉
总结 其实上个月已经做个一个 Jenkins Pipeline 的实践项目,但是上次 Jenkins 和 Gitlab 都是虚拟机安装,没有使用 Docker,所以这次两天的实践基本上是填 Docker 中遇到的坑,端午节假期今天结束了,很庆幸虽然这两天断断续续但还是赶在最后的时间点部署成功了。对 Docker 、 Jenkins 和 Gitlab 这一套技术有了更深的理解。