在公司用了半年的 SpringCloud + Docker + Jenkins 的技术框架,现在流行持续集成,还没有抽点时间自己实际走一下全流程开发环境的搭建,正好赶上端午节,可以宅在出租屋里好好研究一下,特此记录一下实践过程中遇到的问题及解决方案。
搭建测试项目
请求接口
搭建一个简单的SpringBoot项目,创建一个接口用来测试。
接口地址:/api/user-management/users
@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;
}
返回数据格式:
{
"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
FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY springboot-demo.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
EXPOSE 8080
Jenkinsfile
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。
# 安装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:
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
# 修改完之后仓库的地址:
[email protected]: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
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
配置:
# 因为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。
+ 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追加到环境变量中,然后扫描流水线就可以下载依赖了。
# 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
键 | 值 |
---|---|
MAVEN_HOME | /usr/local/maven3 |
PATH+EXTRA | $MAVEN_HOME/bin |
docker命令找不到
解决方案:
给启动的Docker容器挂载宿主机的 docker 环境
/var/run/docker.sock: connect: permission denied
运行到 docker 构建镜像的时候提示权限不足,/var/run/docker.sock 只有 root 权限才能调用,可以将 jenkins 用户加到 docker 组下:
sudo gpasswd -a jenkins docker
newgrp docker
但是这里docker是挂载了宿主机的docker目录,所以不存在docker组,直接将 /var/run/docker.sock 改成 777 权限:
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 这一套技术有了更深的理解。