企业级devops自动化部署学习 (5)jenkins构建镜像并上传到harbor仓库,生产服务器从harbor仓库拉取镜像部署应用
前置准备:Jenkins服务器(192.168.80.134),Docker仓库服务器(192.168.80.135),生产应用部署服务器(192.168.80.136)都安装docker
docker的安装:
https://www.cnblogs.com/lrc123/p/16095016.html
Jenkins拉取代码->编译打包->生成镜像过程
在项目pom.xml中添加dockerfile插件
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.7</version>
<configuration>
<repository>${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
项目根路径下编写dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app.jar"]
文本说明:
from :定义了起始镜像
arg:定义了项目打包后生成的FILE参数,此参数与上面pom.xml的<JAR_FILE>对应
COPY:将项目打包好的JAR文件拷贝到当前工作目录下的app.jar
EXPOSE:暴露8081端口
ENTRYPOINT:相当于执行:java -jar app.jar启动项目
Jenkinsfile中添加构建docker镜像步骤
stage('打包docker镜像') {
steps{
sh 'mvn clean package dockerfile:build'
}
}
提交代码到gitlab远程仓库,并构建项目
构建发现在执行docker build的时候发现报错了:
添加权限:
chmod 777 /var/run/docker.sock
再进行构建:
到jenkins服务器查看镜像:docker images
镜像成功下载到了jenkins服务器。
下面我们运行镜像进行项目访问:
docker run -d -p 8081:8081 gitlab_test_demo
访问项目发现拒绝请求连接了,原因是因为,我当前机器开了防火墙,但是没有开放8081端口
开放8081端口后再访问项目:
firewall-cmd --zone=public --add-port=8081/tcp --permanent
firewall-cmd --reload
发现还是拒绝了请求,我猜想是我的springboot项目内置的tomcat服务器是8080端口,所以docker容器启动应用时也是8080端口,我们做的是8081端口映射,所以存在问题,问题解决:将项目的默认端口改成8081
再上传到gitlab重新构建访问:
成功访问到
镜像推送到Harbor->生产服务器拉取镜像部署项目过程
Harbor简介
Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。除了Harbor这个私有镜像仓库之外,还有Docker官方提供的Registry。相对Registry,Harbor具有很多优势:
1. 提供分层传输机制,优化网络传输 Docker镜像是是分层的,而如果每次传输都使用全量文件(所以用FTP的方式并不适合),显然不经济。必须提供识别分层传输的机制,以层的UUID为标识,确定传输的对象。
2. 提供WEB界面,优化用户体验 只用镜像的名字来进行上传下载显然很不方便,需要有一个用户界面可以支持登陆、搜索功能,包括区分公有、私有镜像。
3. 支持水平扩展集群 当有用户对镜像的上传下载操作集中在某服务器,需要对相应的访问压力作分解。
4. 良好的安全机制 企业中的开发团队有很多不同的职位,对于不同的职位人员,分配不同的权限,
具有更好的安全性。
Harbor安装
此处我的Harhor安装到另一台服务器192.168.80.135上
1、首先安装好docker并启动
2、安装docker-compose
curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
3、给docker-compose添加执行权限
chmod +x /usr/local/bin/docker-compose
4、查看docker-compose是否安装成功
docker-compose -version
5、进入到/opt目录下下载harbor压缩包
cd /opt
wget https://github.com/goharbor/harbor/releases/download/v2.5.0/harbor-offline-installer-v2.5.0.tgz
6、解压harbor
tar -zxvf harbor-offline-installer-v2.5.0.tgz
7、修改harbor配置(修改hostname和port,注释ssl权限认证)
cd /opt/harbor/
vim harbor.yml.tmpl
修改完后将harbor.yml.tmpl改成harbor.yml
mv harbor.yml.tmpl harbor.yml
8、安装harbor
./prepare
./install.sh
安装成功
Harbor的基本使用
1、harbor的相关命令
docker-compose up -d 启动
docker-compose stop 停止
docker-compose restart 重新启动
2、登录harbor
访问地址:http://192.168.80.135:85/
默认的账号密码:admin/Harbor12345
3、创建用户和项目
4、给项目分配用户
这里的角色权限说明
角色 | 权限说明 |
项目管理员 | 拥有读写操作,同时拥有用户管理/镜像扫描等管理权限 |
维护人员 | 对于指定项目拥有读写权限,创建 Webhooks |
开发者 | 对于指定项目拥有读写权限 |
访客 | 对于指定项目拥有只读权限 |
受限访客 | 只可以拉取项目,其他项目资源文件如log没有读权限 |
5、用刚创建的用户登录harbor
jenkins服务器把镜像上传到harbor
1、为已存在镜像打标签
docker tag gitlab_test_demo 192.168.80.135:85/harbor_project01/gitlab_test_demo:v1
2、推送镜像
docker push 192.168.80.135:85/harbor_project/gitlab_test_demo:v1
这条命令出现以上报错,是因为Docker没有把Harbor加入信任列表中 ,下面把Harbor地址加入到docker信任列表
vim /etc/docker/daemon.json
重启docker
systemctl daemon-reload
systemctl restart docker
#如果重启docker失败,可以将daemon.json改成daemon.conf文件
mv /etc/docker/daemon.json /etc/docker/daemon.conf
再次推送还是出现一样的情况:
此时猜想docker.service文件并没有读取到我们daemon.json的配置,下面继续配置docker.service文件
vim /usr/lib/systemd/system/docker.service
再次重启docker推送镜像
又出现了新的认证错误,此时需要先登录到harbor,再推送镜像
#格式:docker login -u 用户名 -p 密码 ip地址:端口
docker login -u admin -p Harbor12345 192.168.80.135:85
再推送镜像
千辛万苦终于推送成功了,到harbor查看:
生产应用部署服务器(192.168.80.136)从Harbor下载镜像
接下来,在新的服务器(192.168.80.136)模拟生产配置的服务器,从Harbor服务器拉取镜像进行项目部署
1、安装docker并启动
2、修改docker配置
vim /usr/lib/systemd/system/docker.service
--insecure-registry 192.168.80.135:85
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.80.135:85"]
}
重启docker
systemctl daemon-reload
systemctl restart docker
#如果重启docker失败,可以将daemon.json改成daemon.conf文件
mv /etc/docker/daemon.json /etc/docker/daemon.conf
3、登录harbor,并下载并镜像
docker login -u admin -p Harbor12345 192.168.80.135:85
docker pull 192.168.80.135:85/harbor_project01/gitlab_test_demo:v1
实际项目部署:jenkins拉取gitlab代码->jenkins中编译打包,生成镜像上传到harbor仓库->生产应用服务器(192.168.80.136)拉取镜像部署
1、jenkins添加harbor凭证
2、创建后,拿出自动生成的id,后边把id配置到项目的Jenkinsfile中
3、jenkins中添加一个project_name环境变量参数,后边如果我们项目添加了,可以通过选择环境变量${project_name}做不同项目的构建
4、使用片段生成器生成替代harbor明文登录信息
5、编写jenkinsfile脚本
pipeline {
environment{
//声明gitlab的凭证
gitlab_auth="4331acf3-f1e0-4e5a-a3c7-b4df55a286c6"
//gitlab项目url
gitlab_url="git@192.168.80.133:test_group01/gitlab_test_demo.git"
//harbor地址
harbor_url="192.168.80.135:85"
//定义镜像标签
tag="latest"
//定义harbor项目名称
harbor_project="harbor_project01"
//定义harbor凭证
harbor_auth="19ceff97-64ad-49f7-b51d-d06661787aaa"
}
agent any
stages {
stage('从gitlab中拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: "${gitlab_auth}", url: "${gitlab_url}"]]])
}
}
stage('编译打包并构建docker镜像') {
steps{
sh "mvn clean package dockerfile:build"
}
}
stage('镜像打标签并上传镜像') {
environment{
//定义镜像名称
imageName="${project_name}:${tag}"
}
steps{
//打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
//镜像推送到harbor
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: "password", usernameVariable: "username")]) {
//登录到harbor
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//镜像上传
sh "docker push ${harbor_url}/${harbor_project}/${imageName}"
}
}
}
}
post {
always {
emailext(
subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} -${BUILD_STATUS}!',
body: '${FILE,path="email.html"}',
to: '11234512@qq.com'
)
}
}
}
6、构建项目
从控制台可以看到镜像推送成功,到harbor仓库查看
7、生产应用服务器拉取镜像并发布服务
(1)jenkins安装publish over ssh插件
我们需要在jenkins服务器(192.168.80.134)中调用远程的生产服务器(192.168.80.136)中拉取镜像并部署,此时需要先安装publish over ssh插件,可以实现远程发送shell命令
(2)在jenkins服务器(192.168.80.134)中拷贝公钥到远程生产服务器(192.168.80.136)中
ssh-copy-id 192.168.80.136
到生产服务器(192.168.80.136)中查看:
(3)在jenkins配置添加远程ssh
(3.1)在configure system的publish over ssh中填入私钥
私钥获取:
cat /root/.ssh/id_rsa
(3.2)配置ssh server
(3.3)测试连接
(4)在生产服务器编写一个shell脚本,完成项目的部署操作
(4.1)创建/opt/jenkins_shell目录,并进入到该目录
mkdir /opt/jenkins_shell
cd /opt/jenkins_shell
(4.2)创建文件deploy.sh,编写部署脚本
touch deploy.sh
vim deploy.sh
脚本如下:
#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project=$2
project_name=$3
tag=$4
port=$5
imageName=$harbor_url/$harbor_project/$project_name:$tag
echo "$imageName"
#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'`
if [ "$containerId" != "" ] ; then
#停掉容器
docker stop $containerId
#删除容器
docker rm $containerId
echo "成功删除容器"
fi
#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name | awk '{print $3}'`
if [ "$imageId" != "" ] ; then
#删除镜像
docker rmi -f $imageId
echo "成功删除镜像"
fi
# 登录Harbor
docker login -u admin -p Harbor12345 $harbor_url
# 下载镜像
docker pull $imageName
# 启动容器
docker run -di -p $port:$port $imageName
echo "容器启动成功"
(4.3)给deploy.sh脚本添加可执行权限
chmod +x deploy.sh
(5)在jenkins添加一个port参数,参数化项目暴露的端口
(6)修改Jenkinsfile
pipeline {
environment{
//声明gitlab的凭证
gitlab_auth="4331acf3-f1e0-4e5a-a3c7-b4df55a286c6"
//gitlab项目url
gitlab_url="git@192.168.80.133:test_group01/gitlab_test_demo.git"
//harbor地址
harbor_url="192.168.80.135:85"
//定义镜像标签
tag="latest"
//定义harbor项目名称
harbor_project="harbor_project01"
//定义harbor凭证
harbor_auth="19ceff97-64ad-49f7-b51d-d06661787aaa"
}
agent any
stages {
stage('从gitlab中拉取代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: "${gitlab_auth}", url: "${gitlab_url}"]]])
}
}
stage('编译打包并构建docker镜像') {
steps{
sh "mvn clean package dockerfile:build"
}
}
stage('镜像打标签并上传镜像') {
environment{
//定义镜像名称
imageName="${project_name}:${tag}"
}
steps{
//打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
//镜像推送到harbor
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: "password", usernameVariable: "username")]) {
//登录到harbor
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//镜像上传
sh "docker push ${harbor_url}/${harbor_project}/${imageName}"
}
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project}/${imageName}"
}
}
stage('远程部署应用'){
steps{
sshPublisher(publishers: [sshPublisherDesc(configName: 'product_server',transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand:"/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false,
noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '',remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
post {
always {
emailext(
subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} -${BUILD_STATUS}!',
body: '${FILE,path="email.html"}',
to: '11234512@qq.com'
)
}
}
}
(7)构建执行
控制台看到部署成功了,此时我们在生产服务器访问项目:192.168.80.136:8081/hello
自此,一整套的自动化部署流程已经完成,回顾流程示意图: