持续集成技术总结

一、DockerMaven插件的使用

这个插件的目的就是,能够把本地项目远程打包到docker,并生成相应的镜像。

微服务部署有两种方法:

(1)手动部署:首先基于源码打包生成jar包(或war包),将jar包(或war包)上传至虚 拟机并拷贝至JDK容器。

(2)通过Maven插件自动部署。

对于数量众多的微服务,手动部署无疑是非常麻烦的做法,并且容易出错。所以我们这 里学习如何自动部署,这也是企业实际开发中经常使用的方法

而且使用dockermaven插件自动部署项目,有两种方式,一种是编写Dockerfile方式,一种是纯xml方式。第一种方式在本人的总结的《Docker总结》第十二章有写到。下面的案例主要是讲解通过xml的方式部署项目。

其实他们本质上是一样的

Maven插件自动部署步骤:

(1)修改宿主机的docker配置,让其可以远程访问

Vi /lib/systemd/system/docker.service

其中ExecStart=后添加配置

‐H tcp://0.0.0.0:2375 ‐H unix:///var/run/docker.sock

修改后如下:

img

(2)刷新配置,重启服务

systemctl daemon‐reload

systemctl restart docker

docker start registry

注意:这里的registry是本人新建的本地仓库(怎么新建本地仓库以及怎么使用,参见docker的文章)-当然你也可以把镜像提交到阿里云镜像仓库中。

使用SpringBoot2.0+DockerFile+Maven插件构建镜像并推送到阿里云仓库

https://blog.csdn.net/haogexiang9700/article/details/88318867

(3)在工程pom.xml 增加配置

<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐maven‐plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker‐maven‐plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>192.168.1.105:5000/${project.artifactId}:${project.version} </imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "‐jar", "/${project.build.finalName}.jar"]
</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory} </directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://192.168.1.105:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
app org.springframework.boot spring‐boot‐maven‐plugin com.spotify docker‐maven‐plugin 0.4.13 192.168.1.105:5000/${project.artifactId}:${project.version} jdk1.8 [“java”, “‐jar”, “/${project.build.finalName}.jar”] / ${project.build.directory} ${project.build.finalName}.jar http://192.168.1.105:2375

以上配置会自动生成Dockerfile

FROM jdk1.8 ADD app.jar / ENTRYPOINT [“java”,”‐jar”,”/app.jar”]

创建一个镜像,继承自jdk1.8,同时拷贝本地的app.jar到镜像的根目录。在容器启动时,执行java –jar /app.jar(也就是启动项目)

(4)在windows的命令提示符下,进入工程app所在的目录,进行打包和上传镜像

mvn install

mvn docker:build ‐DpushImage

执行后,会有如下输出,代码正在上传

img

(6)进入宿主机 , 查看镜像

Docker images

img

(7)启动容器

img

img

访问成功!!!

二、持续集成工具Jenkins

官网:https://jenkins.io/zh/doc/tutorials/build-a-java-app-with-maven/

主要是解决自动化构建项目,发布项目等等问题。

微服务架构下,带来了运维上的额外复杂性,尤其是在服务部署和服务监控上。单体应用是集中式的,就一个单体跑在一起,部署和管理的时候非常简单。而微服务是一个网状分布的,有很多服务需要维护和管理,对它进行部署和维护的时候则比较复杂,所以就需要一个工具能够自动化的完成自动编译、发布和测试,从而尽快地发现集成错误,让团队能够更快的开发内聚的软件。

**持续集成具有的特点:**

它是一个自动化的周期性的集成测试过程,从检出代码、编译构建、运行测试、结果 记录、测试统计等都是自动完成的,无需人工干预;

需要有专门的集成服务器来执行集成构建;

需要有代码托管工具支持,我们下一小节将介绍Git以及可视化界面Gogs的使用

持续集成的作用:

保证团队开发人员提交代码的质量,减轻了软件发布时的压力;

持续集成中的任何一个环节都是自动完成的,无需太多的人工干预,有利于减少重复 过程以节省时间、费用和工作量;

基本思路:

https://www.centos.bz/wp-content/uploads/2017/11/1-17.jpg

1.Jenkins简介

Jenkins,原名Hudson,2011年改为现在的名字,它 是一个开源的实现持续集成的 软件工具。官方网站:http://jenkins-ci.org/。

Jenkins 能实施监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用图 表的形式形象地展示项目构建的趋势和稳定性。

特点:

易安装:仅仅一个 java -jar jenkins.war,从官网下载该文件后,直接运行,无需额 外的安装,更无需安装数据库;

易配置:提供友好的GUI配置界面;

变更支持:Jenkins能从代码仓库(Subversion/CVS)中获取并产生代码更新列表并 输出到编译输出信息中;

支持永久链接:用户是通过web来访问Jenkins的,而这些web页面的链接地址都是 永久链接地址,因此,你可以在各种文档中直接使用该链接;

集成E-Mail/RSS/IM:当完成一次集成时,可通过这些工具实时告诉你集成结果(据 我所知,构建一次集成需要花费一定时间,有了这个功能,你就可以在等待结果过程 中,干别的事情);

JUnit/TestNG**测试报告:**也就是用以图表等形式提供详细的测试报表功能;

支持分布式构建:Jenkins可以把集成构建等工作分发到多台计算机中完成;

文件指纹信息:Jenkins会保存哪次集成构建产生了哪些jars文件,哪一次集成构建使 用了哪个版本的jars文件等构建记录;

支持第三方插件:使得 Jenkins 变得越来越强大

2. Jenkins安装

资源准备

img

当然你可以通过wget命令进行下载相应的rpm包

2.1 JDK安装

(1)将jdk-8u171-linux-x64.rpm上传至服务器(虚拟机)

(2)执行安装命令

rpm ‐ivh jdk‐8u171‐linux‐x64.rpm

(3)查看是否安装成功

img

因为rpm包已经自动为我们做了相关的环境变量配置,所以不需要额外配置(相关的命令在 /usr/bin)

2.2 maven安装

(1)将 apache‐maven‐3.5.4‐bin.tar.gz上传至服务器(虚拟机)

(2)解压

tar zxvf apache‐maven‐3.5.4‐bin.tar.gz

img

(3))编辑setting.xml配置文件

vi /opt/software/apache-maven-3.5.4/conf/settings.xml

增加如下配置

/opt/software/mavenRepostory

(4)将开发环境(win10)的本地仓库上传至服务器(虚拟机)并移动到/opt/software/mavenRepostory

执行此步是为了以后在打包的时候不必重新下载,缩短打包的时间

2.3 Jenkins安装与启动

在安装jenkins之前必须要安装jdk。

(1)下载jenkins

wget https://pkg.jenkins.io/redhat/jenkins‐2.83‐1.1.noarch.rpm

或将应下载好的jenkins-2.83-1.1.noarch.rpm上传至服务器

https://pkg.jenkins.io/redhat-stable/ 官网下载(建议下载最新版本,避免安装插件时报错 jenkins-2.187-1.1.noarch.rpm)

(2)安装jenkins

rpm ‐ivh jenkins‐2.83‐1.1.noarch.rpm

自动安装完成之后:

/usr/lib/jenkins/jenkins.war WAR**包**

/etc/sysconfig/jenkins 配置文件

/var/lib/jenkins/ 默认的JENKINS_HOME目录

/var/log/jenkins/jenkins.log Jenkins**日志文件**

(3)配置jenkins

vi /etc/sysconfig/jenkins

修改用户和端口

JENKINS_USER=”root” JENKINS_PORT=”8888”

(4)启动服务

systemctl start Jenkins

(5)访问链接 http://49.234.188.74:8888

从/var/lib/jenkins/secrets/initialAdminPassword中获取初始密码串

img

(6)安装插件

img

选择推荐安装,避免漏掉一些jenkins必须依赖的插件,后面有额外需要的插件我们还可以手动安装

安装插件中

img

需要注意的是,在安装插件的可能会失败,一般是因为当前jenkins版本太低的原因,可以先忽略错误,进去后更新jenkins为新的版本,插件自己会自动安装成功。

(7)新建用户

完成安装进入主界面

img

3. Jenkins插件安装

我们以安装maven插件为例,演示插件的安装

(1)点击左侧的“系统管理”菜单 ,然后点点击

img

img

img

4.全局工具配置

选择系统管理,全局工具配置

img

(1)JDK配置

img

设置javahome为 /usr/java/jdk1.8.0_171-amd64

(2)Git配置 (本地已经安装了Git软件)

如果linux 没有安装过git。那么可以参考 《额外补充》第三章节进行安装。

img

如果不知道本地git的地址可以使用命令:whereis git 获取地址。

默认在启动jenkins时,应安装好了git插件

img

(3)Maven配置

img

然后保存即可,接下来上传代码到git,然后创建任务。

5 代码上传至Git服务器

5.1 Gogs搭建与配置

Gogs 是一款极易搭建的自助 Git 服务。

Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语 言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包 括 Linux、Mac OS X、Windows 以及 ARM 平台

地址:https://gitee.com/Unknown/gogs

(1)下载镜像

docker pull gogs/gogs

(2)创建容器

docker run -d -p 10022:22 -p 10080:3000 \

–name=gogs \

-v /opt/docker/gogs/:/data \

gogs/gogs

(3)安装gogs

在地址栏输入 http://49.234.188.74: 10080/,会进入首次运行安装程序页面,我们可以选择一种数据 库作为gogs数据的存储,最简单的是选择SQLite3。如果对于规模较大的公司,可以选择 MySQL

img

点击“立即安装”

这里的域名要设置为centos的IP地址,安装后显示主界面

(4)注册

img

(5)登录

img

登陆后

img

(6)创建仓库

img

img

5.2 提交代码到git

步骤:

(1)在本地安装git(Windows版本)

(2)在IDEA中选择菜单 : File – settings , 在窗口中选择Version Control – Gi

img

(3)选择菜单VCS –> Enable Version Control Integration

(4)设置远程地址: 右键点击工程选择菜单 Git –> Repository –>Remotes…

img

img

url填写我们之前用gogs创建的git仓库:http://49.234.188.74:10080/root/kingge.git

(5)右键点击工程选择菜单 Git –> Add

(6)右键点击工程选择菜单 Git –> Commit Directory…

(7)右键点击工程选择菜单 Git –> Repository –> Push …

img

6 jenkins任务的创建与执行

(1)回到首页,点击新建按钮 .如下图,输入名称,选择创建一个Maven项目,点击OK

img

(2)源码管理,选择Git

img

(3)填写构建语句

img

clean package docker:build ‐DpushImage

(4)查看项目

img

我们点击执行后,可以看到左下角出现这个任务进度

img

这样就能够上传成功了

7.总结

通过jenkins,我们可以很好的集成、部署了我们开发的项目,自动构建项目的镜像,这样为我们节省了很多的时间。

三、容器管理工具Rancher

管理docker和Kubernetes容器,通过可视化界面的方式,管理,部署,启动docker容器,同时支持分布式集群部署docekr容器。

1.安装Rancher

Rancher是一个开源的企业级全栈化容器部署及管理平台。Rancher为容器提供一揽 子基础架构服务:CNI兼容的网络服务、存储服务、主机管理、负载均衡、防护墙…… Rancher让上述服务跨越公有云、私有云、虚拟机、物理机环境运行,真正实现一键式应 用部署和管理

https://www.cnrancher.com/

(1)下载Rancher 镜像

docker pull rancher/server

(2)创建Rancher容器

docker run ‐di ‐‐name=rancher ‐p 9090:8080 rancher/server

(3)在浏览器输入地址: http://192.168.184.136:9090

img

2.初始化Rancher

2.1 添加环境

Rancher 支持将资源分组归属到多个环境。 每个环境具有自己独立的基础架构资源及服 务,并由一个或多个用户、团队或组织所管理。

例如,您可以创建独立的“开发”、“测试”及“生产”环境以确保环境之间的安全隔离,将“开 发”环境的访问权限赋予全部人员,但限制“生产”环境的访问权限给一个小的团队。

(1) 选择“Default –>环境管理” 菜单

img

(2)填写名称,点击“创建”按钮

img

img

可以添加多个环境,分别给区分不同用户使用场景

(4))你可以通过点击logo右侧的菜单在各种环境下切换

img

2.2 添加主机

(1)选择基础架构–>主机 菜单,点击添加主机

img

img

直接保存,当然你也可以选择其他主机(管理非当前服务器)

(2)拷贝脚本,主机和rancher服务建立连接

img

(3)在主机上运行脚本

img

(4)点击关闭按钮后,会看到界面中显示此主机。我们可以很方便地管理主机的每个容 器的开启和关闭

img

在这里可以看到当前主机下,已经创建好的容器

2.3 添加应用

(1)点击应用–>全部(或用户) ,点击“添加应用”按钮

img

img

img

应用是多个服务的载体。例如一个mysql容器就是一个服务,它提供数据库服务。例如redis也是一个服务等等。

2.4 添加服务

相对于docker而言,添加一个服务就等同于创建一个容器

2.4.1 添加mysql服务

镜像:mysql:latest 增加mysql数据库服务

img

打开我们在2.3节创建的应用,然后点击创建服务

img

img

点击创建按钮,完成创建。上述操作相当于以下docker命令

docker run ‐di ‐‐name mysql ‐p 3306:3306 ‐e MYSQL_ROOT_PASSWORD=123456 mysql:latest

创建中

img

创建完毕

img

2.4.2 添加RabbitMQ服务

镜像:rabbitmq:management 端口映射5671 5672 4369 15671 15672 25672

img

2.4.3 Redis服务

img

img

2.5 部署我们在第一章节dockermaven构建的app容器

img

开始部署服务

img

点击创建部署中

img

创建成功

img

访问

img

3. rancher的扩容与缩容

就是对某个服务(容器)进行数量的增加或者减少,因为我们知道大型的项目一个服务是部署到多台服务器的,构建成一个服务集群,是为了应变访问量的高低。所以rancher也是提供了这种功能。

一下例子,以我们在上面构建的app服务为例子。

(1)部署app服务,不指定端口

这里为什么不指定端口,因为假设我们把服务扩容到两台,那么端口号就会冲突,所以这里让docker为我们默认分配端口。

img

img

(2)在选择菜单API –>WebHooks ,点击“添加接收器”按钮

img

(3)填写名称等信息,选择要扩容的服务,点击创建按钮

img

创建成功

img

提供了一个触发扩容操作的url

http://192.168.1.105:9090/v1-webhooks/endpoint?key=ctm3rFpH6oAsbOA5mXMHvZyW7BoCkz1QQgpw00ay&projectId=1a5

(4)测试扩容服务

必须使用post的方式,触发上面提供的url

img

在触发之前,我们先查看一下app服务的数量

img

是一个

开始触发

img

img

扩容成功,数量变成了3

那么这个时候,我么你会有个疑问,我们怎么访问这些服务呢?这些服务并没有提供对外暴露的端口?

答案是:采用创建负载均衡服务的方式访问

4.负载均衡

(1)创建负载均衡服务

img

img

创建负载均衡服务中

img

创建成功

img

尝试访问

img

访问成功,他会通过轮询的方式访问这三台容器。

四、时间序列数据库influxDB

他主要是用来存储一些实时的数据,例如下面我们将会学习的cAdvisor,监控容器的内存相关的信息,就是存储在influDB中。记住他并不是用来存储大量数据的,不是mysql这样类型的数据库。

1. 什么是influxDB

influxDB是一个分布式时间序列数据库。cAdvisor仅仅显示实时信息,但是不存储 监视数据。因此,我们需要提供时序数据库用于存储cAdvisor组件所提供的监控信息, 以便显示除实时信息之外的时序数据。

2 influxDB安装

(1)下载镜像

docker pull tutum/influxdb

(2)创建容器

docker run ‐di \

‐p 8083:8083 \

‐p 8086:8086 \

‐‐expose 8090 \

‐‐expose 8099 \

‐‐name influxsrv \

tutum/influxdb

端口概述: 8083端口:web访问端口 8086:数据写入端口 (后面启动adviosr的时候会用到

docker run -di -p 8083:8083 -p 8086:8086 –expose 8090 –expose 8099 –name influxsrv tutum/influxdb

打开浏览器 http://192.168.1.105:8083/

img

3 influxDB常用操作

3.1 创建数据库

CREATE DATABASE “cadvisor”

回车创建数据库

img

查看数据库

SHOW DATABASES

img

3.2 创建用户并授权

创建用户

CREATE USER “cadvisor” WITH PASSWORD ‘cadvisor’ WITH ALL PRIVILEGES

查看用户

SHOW USRES

img

用户授权

grant all privileges on cadvisor to cadvisor (on后面跟的是数据库名,to后面跟的是 用户名)

grant WRITE on cadvisor to cadvisor

grant READ on cadvisor to cadvisor

3.3 查看采集的数据

切换到cadvisor数据库,使用以下命令查看采集的数据

SHOW MEASUREMENTS

现在我们还没有数据,如果想采集系统的数据,我们需要使用Cadvisor软件来实现

五、容器监控工具cAdvisor

1 什么是cAdvisor

Google开源的用于监控基础设施应用的工具,它是一个强大的监控工具,不需要任何配置就可以通过运行在Docker主机上的容器来监控Docker容器,而且可以监控Docker 主机。更多详细操作和配置选项可以查看Github上的cAdvisor项目文档。

2 cAdvisor安装

(1)下载镜像

docker pull google/cadvisor

(2)创建容器

docker run –volume=/:/rootfs:ro –volume=/var/run:/var/run:rw –volume=/sys:/sys:ro –volume=/var/lib/docker/:/var/lib/docker:ro –publish=8080:8080 –detach=true –link influxsrv:influxsrv –name=cadvisor google/cadvisor -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086

我们可以看到启动cadvisor容器时,可以看到storage_driver 指定了存储的用的数据库,storage_driver_db指定了用的数据库名称,storage_driver_host指定写入数据库地址,–link 表示连接到我们在上面创建的influxsrv容器

(3)查看容器

WEB前端访问地址 http://192.168.1.105:8080/containers/

img

img

性能指标含义参照如下地址

https://blog.csdn.net/ZHANG_H_A/article/details/53097084

(4)查看influxsrv容器

再次查看influxDB,发现已经有很多数据被采集进去了

img

可以使用select语句查询某张表的数据

img

3.总结

经过上面的学习,cadvisor和influxsrv 的使用我们可以检测采集,以及采集数据保存到influxdb中,但是有个缺点,那就是采集到infludb的数据,通过select语句查询,不是那么直观,那么下面我们将使用grafana图表工具展示influx的数据。

六、图表工具Grafana

1 什么是Grafana

Grafana是一个可视化面板(Dashboard),有着非常漂亮的图表和布局展示,功能齐全的度量仪表盘和图形编辑器。支持Graphite、zabbix、InfluxDB、Prometheus和 OpenTSDB作为数据源。 Grafana主要特性:灵活丰富的图形化选项;可以混合多种风格;支持白天和夜间模式,多个数据源。

2 Grafana安装

(1)下载镜像

docker pull grafana/grafana

(2)创建容器

docker run -d -p 3001:3000 -e INFLUXDB_HOST=influxsrv -e INFLUXDB_PORT=8086 -e INFLUXDB_NAME=cadvisor -e INFLUXDB_USER=root -e INFLUXDB_PASS=itcast –link influxsrv:influxsrv –name=grafana grafana/grafana

(3)访问

http://192.168.1.105:3001

用户名密码均为admin

img

登录后需要修改密码,密码修改为:123456

(4)之后进入主页面

img

(5)添加数据源

img

img

选择InfluxDB

(5)填写数据源信息

img

点击save

img

连接成功

(5)添加仪表盘

选择Dashboards –Manager

img

img

然后选择展示数据的图表样式

img

这里我们选择第一个,柱状图

(6)设置图表数据源

img

进入下个界面

img

点击edit

img

然后点击右上角保存即可

(6)预警通知设置

(1)选择菜单 alerting–> Notification channels

(2)点击Add channel 按钮

(3)填写名称,选择类型为webhook ,填写钩子地址

这个钩子地址是之前对base微服务扩容的地址

(4)点击SendTest 测试 观察基础微服务是否增加容器

(5)点击save保存

(6)按照同样的方法添加缩容地址 6.4.4 仪表盘预警设置

(7)再次打开刚刚编辑的仪表盘

(8)点击 Create Alert

设置预警线

(9)选择通知

保存更改

总结

Influxdb和cadvisor、grafana,这三者一般都是一起使用,cadvisor负责往influxdb里面写入监控的数据,grafana负责从infuxdb中读取数据,并做可视化显示。

img

额外补充

1 使用docker安装jenkins

在第二章节中我们是使用rpm的方式安装jenkins,其实我们也是可以使用docker镜像的方式安装jenkins。但是这种方式创建数据卷会存在权限问题,所以一般也不常用

https://hub.docker.com/_/jenkins/ 官网。注意查看jenkins容器启动后配置文件在容器中的位置,方便我们设置容器卷链接到本地虚拟机

img

1.1 下载jenkins镜像

docker pull jenkins

img

1.2 启动jenkins容器

在镜像文档里,我们知道Jenkins访问的端口号是8080,另外还需要暴露一个tcp的端口号50000。我们使用如下命令启动Jenkins镜像

1.首先创建本地挂载目录并修改权限

创建目录赋权限

mkdir /home/jenkins

ls -nd jenkins

chown -R 1000:1000 jenkins/ (设置权限)

为什么需要修改本地数据卷文件的权限呢?

我们首先查看一下jenkins容器数据卷的权限信息

img

如果不把全权限修改一致,那么当本地数据卷信息同步到容器数据卷目录的时候,就会出现没有权限的问题。

https://www.cnblogs.com/jackluo/p/5783116.html 可以查看这篇文章。

\2. docker run -itd -p 6666:8080 -p 6660:50000 –name jenkins –privileged=true -v /home/jenkins:/var/jenkins_home jenkins

img

1.3 开始安装

访问

http://192.168.1.105:6666

img

查看初始化密码

img

位置在我们关联的本地数据卷目录中

如果安装过程中出现下面这个错误

img

说明需要更换jenkin安装插件地址

img

img

2. Docker Volume 之权限管理

https://www.cnblogs.com/jackluo/p/5783116.html

1.启动Jenkins官方镜像,并检查日志

docker run -d -p 8080:8080 -p 50000:50000 –name jenkins jenkin

docker logs jenkins

我们可以发现”jenkins”容器日志显示结果一切正常

2.然而为了持久化Jenkins配置数据,当我们把宿主机当前目录下的data文件夹挂载到容器中的目录”/var/jenkins_home”的时候,问题出现了:

docker rm -f jenkins

docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home –name jenkins jenkins

docker logs jenkins

错误日志如下

touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied

Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

\3. 我们检查一下之前启动方式的”/var/jenkins_home”目录权限,查看Jenkins容器的当前用户: 当前用户是”jenkins”而且”/var/jenkins_home”目录是属于jenkins用户拥有的

docker@default:~$ docker run -ti –rm –entrypoint=”/bin/bash” jenkins -c “whoami && id” jenkins uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins) docker@default:~$ docker run -ti –rm –entrypoint=”/bin/bash” jenkins -c “ls -la /var/jenkins_home” total 20 drwxr-xr-x 2 jenkins jenkins 4096 Jun 5 08:39 . drwxr-xr-x 28 root root 4096 May 24 16:43 .. -rw-r–r– 1 jenkins jenkins 220 Nov 12 2014 .bash_logout -rw-r–r– 1 jenkins jenkins 3515 Nov 12 2014 .bashrc -rw-r–r– 1 jenkins jenkins 675 Nov 12 2014 .profile

而当映射本地数据卷时,/var/jenkins_home目录的拥有者变成了root用户

docker run -ti –rm -v $(pwd)/data:/var/jenkins_home –entrypoint=”/bin/bash” jenkins -c “ls -la /var/jenkins_home”

total 4

drwxr-sr-x 2 root staff 40 Jun 5 08:32 .

drwxr-xr-x 28 root root 4096 May 24 16:43 ..

这就解释了为什么当”jenkins”用户的进程访问”/var/jenkins_home”目录时,会出现 Permission denied 的问题

我们再检查一下宿主机上的数据卷目录,当前路径下”data”目录的拥有者是”root”,这是因为这个目录是Docker进程缺省创建出来的。

docker@default:~$ ls -la data

total 0

drwxr-sr-x 2 root staff 40 Jun 5 08:32 ./

drwxr-sr-x 5 docker staff 160 Jun 5 08:32 ../

发现问题之后,相应的解决方法也很简单:把当前目录的拥有者赋值给uid 1000,再启动”jenkins”容器就一切正常了。

sudo chown -R 1000 data

docker start jenkins

这时利用浏览器访问 “http://192.168.99.100:8080/“ 就可以看到Jenkins的Web界面了。注:如无法访问,可能需要通过docker-machine ip命令获得当前Docker宿主机的IP地址。

当我们再进入容器内部查看”/var/jenkins_home”目录的权限,其拥有者已经变成 “jenkins”

复制代码

docker@default:~$ docker exec jenkins ls -la /var/jenkins_home

total 24

drwxr-sr-x 11 jenkins staff 340 Jun 5 09:00 .

drwxr-xr-x 28 root root 4096 May 24 16:43 ..

drwxr-sr-x 3 jenkins staff 60 Jun 5 08:59 .java

-rw-r–r– 1 jenkins staff 289 Jun 5 08:59 copy_reference_file.log

复制代码

而有趣的是在宿主机上我们看到的 “data”目录的拥有者是”docker”,这是因为”docker”用户在”boot2docker”宿主机上的uid也是”1000”。

docker@default:~$ ls -la data

total 20

drwxr-sr-x 2 docker staff 40 Jun 5 11:55 ./

drwxr-sr-x 6 docker staff 180 Jun 5 11:55 ../

这时我们已经可以知道:容器的本地数据卷中文件/目录的权限是和宿主机上一致的,只是uid/gid在Docker容器和宿主机中可能映射为不同的用户/组名称。

在上文,我们使用了一个常见的技巧,即在宿主机上执行chown命令时采用了uid而不是具体的用户名,这样就可以保证设置正确的拥有者。

问题虽然解决了,但思考并没有结束。因为当使用本地数据卷时,Jenkins容器会依赖宿主机目录权限的正确性,这会给自动化部署带来额外的工作。有没有方法让Jenkins容器为数据卷自动地设置正确的权限呢?这个问题对很多以non-root方式运行的应用也都有借鉴意义。

为non-root应用正确地挂载本地数据卷

我们可以从万能的stackoverflow.com找到很多相关的讨论,其中一个非常有借鉴意义问答如下

http://stackoverflow.com/questions/23544282/what-is-the-best-way-to-manage-permissions-for-docker-shared-volumes

其中的基本思路有两个:

一个是利用Data Container的方法在容器间共享数据卷。这样就规避了解决宿主机上数据卷的权限问题。由于在1.9版本之后,Docker提供了named volume来取代纯数据容器,我们还需要真正地解决这个问题。

另外一个思路就是让容器中以root用户启动,在容器启动脚本中利用”chown”命令来修正数据卷文件权限,之后切换到non-root用户来执行程序

我们来参照第二个思路来解决这个问题

下面是一个基于Jenkins镜像的Dockerfile:它会切换到”root”用户并在镜像中添加”gosu”命令,和新的入口点”/entrypoint.sh”

FROM jenkins:latest USER root RUN GOSU_SHA=5ec5d23079e94aea5f7ed92ee8a1a34bbf64c2d4053dadf383992908a2f9dc8a \ && curl -sSL -o /usr/local/bin/gosu “https://github.com/tianon/gosu/releases/download/1.9/gosu-$(dpkg –print-architecture)” \ && chmod +x /usr/local/bin/gosu \ && echo “$GOSU_SHA /usr/local/bin/gosu” | sha256sum -c - COPY entrypoint.sh /entrypoint.sh ENTRYPOINT [“/entrypoint.sh”]

注释:gosu 是经常出现在官方Docker镜像中的一个小工具。它是”su”和”sudo”命令的轻量级替代品,并解决了它们在tty和信号传递中的一些问题。

新入口点的”entrypoint.sh”的内容如下:它会为”JENKINS_HOME”目录设置”jenkins”的拥有权限,并且再利用”gosu”命令切换到”jenkins”用户来执行”jenkins”应用。

#! /bin/bash

set -e

chown -R 1000 “$JENKINS_HOME”

exec gosu jenkins /bin/tini – /usr/local/bin/jenkins.sh

您可以直接从 https://github.com/denverdino/docker-jenkins 获得相关代码,并构建自己的Jenkins镜像。执行命令如下:

git clone https://github.com/AliyunContainerService/docker-jenkins

cd docker-jenkins/jenkins

docker build -t denverdino/jenkins .

然后基于新镜像启动Jenkins容器

docker rm -f jenkins

docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home –name jenkins denverdino/jenkins

3.linux安装git

3.1 使用yum命令进行安装

yum install git

安装简单,但是安装的git版本太老,而且版本不好控制,推荐使用下面的方式进行安装

3.2 源码编译安装Git

①、获取github最新的Git安装包下载链接,进入Linux服务器,执行下载,命令为: wget https://github.com/git/git/archive/v2.22.0.tar.gz

img

②、压缩包解压,命令为: tar -zxvf v2.22.0.tar.gz ;

img

③、安装编译源码所需依赖,命令为: yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker

耐心等待安装,出现提示输入y即可;

④、安装依赖时,yum自动安装了Git,需要卸载旧版本Git,命令为: yum remove git 出现提示输入y即可;

img很明显自己安装了一个1.8.3.1版本的git,卸载。

⑤、进入解压后的文件夹,命令 cd git-2.22.0 ,然后执行编译,命令为 make prefix=/usr/local/git all 耐心等待编译即可;

⑥、安装Git至/usr/local/git路径,命令为 make prefix=/usr/local/git install ;

⑦、打开环境变量配置文件,命令 vim /etc/profile ,在底部加上Git相关配置信息:

PATH=$PATH:/usr/local/git/bin

export PATH

然后保存,退出!

⑧、输入命令 git –version ,查看安装的git版本,校验通过,安装成功。

source /etc/profile

img

如果你感觉文章对你又些许感悟,你可以支持我!!
-------------本文结束感谢您的阅读-------------