2018-10-03 docker构建本地ci环境
看到docker的介绍,感觉这个东西用于在本地构建环境还是非常好用的。他不仅免除了大量的配置过程,还让电脑环境干净。当需要删除一个应用时,只需要停止对应的docker容器,然后删除即可。因此,尝试在本地使用docker来构建jenkins+nexus的个人构建环境。
关于docker的基础知识,直接看官方中文网站上的例子就足够了,我就不啰嗦了。
官方中文网站,上面有官方入门教程的翻译
还有RUNOOB也很不错
自己看帖子就好。
1. 首先,是安装docker-ce
根据官方提供的centos安装docker-ce的例子代码:
dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
考虑,docker是否其实也有提供fedora的软件源呢?输入
http://mirrors.aliyun.com/docker-ce/linux/
发现果然有提供fedora发行版本的软件源:
![](https://img.haomeiwen.com/i14097738/c4dc844997a04a05.png)
于是执行如下代码:
dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/fedora/docker-ce.repo
检查dnf软件源列表,可以发现docker软件源已经可用:
dnf repolist
结果如下:
![](https://img.haomeiwen.com/i14097738/573307b716555b28.png)
好了,现在可以安装docker了。最新版本的docker,根据社区和企业商用,提供了不同的发行版,分别是docker-ce 和 docker-ee,商用版(也就是docker-ee)需要付费。我们个人使用,docker-ce 就可以了:
dnf -y install docker-ce
安装docker过程到此为止。等安装完毕后,执行service docker start 就可以启动docker守候进程了。
接下来,就可以访问镜像仓库了。如果觉得使用官方镜像仓库站点在国外,访问太慢,可以配置aliyun的docker镜像仓库代理。具体操作可以在登陆aliyiun控制台后,看阿里的这篇文章。
2. 安装 nexus
先检查是否已经存在nexus的镜像。可以直接上docker的官方镜像仓库搜索,也可以直接执行docker命令搜索:
docker search nexus
可以看到有官方提供的镜像:
![](https://img.haomeiwen.com/i14097738/523992ab041916c2.png)
于是,执行如下命令来下载nexus3的镜像:
docker pull sonatype/nexus3
之后,可以使用命令查看本地的镜像列表:
docker images
可以看到,我本地已经有了该镜像:
![](https://img.haomeiwen.com/i14097738/dde45a4011a937af.png)
这样,接下来就可以安装容器了。
在这里,有几个问题需要注意:
- docker的运行容器中的端口,和主机的端口需要映射,否则无法访问
- docker容器内的软件存储路径,和主机的文件系统存储路径,需要进行映射,否则你很难访问容器内软件的资料。
我的做法,是将各种容器的创建脚本写在对应的.sh 文件内,然后存放在/install/docker 目录下。
对于nexus,其创建容器的脚本文件 create-nexus.sh 内容如下:
docker run -d -p 8081:8081 --name nexus -v /appdata/nexus:/nexus-data sonatype/nexus3
其中:
- -d 表示该容器以独立进程运行
- -p 8081:8081 表示主机端口8081(冒号前的8081)用于映射到容器内的8081端口(冒号后的8081)。原因是在nexus的容器的makefile中,我们可以看到nexus的运行端口就是8081。
- --name nexus 表示将该容器命名为 nexus,以后可以通过该名字操作该容器
- -v /appdata/nexus:/nexus-data 表示将主机的 /appdata/nexus 映射到 容器内的/nexus-data 目录。原因是在 nexus容器的makefile中,nexus使用容器内的 /nexus-data 目录作为数据目录使用。
- sonatype/nexus3 命令最后的这个字串,是镜像的名字,表示使用该镜像来创建容器。
好了,创建容器的脚本就好了。但在正式执行该脚本之前,还需要对主机上的 /appdata/nexus 目录进行预处理,否则启动容器时将因为没有权限而失败,因为容器内的用户,和主机的用户是独立,没有关系的:
$cd /appdata
$mkdir nexus
$chmod 777 /appdata/nexus
好了,现在可以通过这个命令来启动nexus的容器了:
docker start nexus
如果不使用该容器了,可以通过如下命令停止容器:
docker stop nexus
其中,nexus是我们创建容器时给容器取的名字。
如果要查看nexus的日志,可以通过如下命令:
docker logs -f nexus
该指令等同于查看本地安装应用的日志文件的命令:
tail -100f xxx.log
如果要查看容器内的进程,可以执行如下命令:
docker top
如果容器操作错了,想重新安装nexus,也非常简单快捷:
$docker stop nexux
$docker rm nexux
$cd /appdata
$rm -rf /appdata/nexus
$cd /install/docker
$./create-nexus.sh
可以通过
http://localhost:8180/nexus
来访问刚安装好的nexus,其默认管理员账号是 admin/admin123
2. 安装jenkins
首先在docker官方仓库网页搜索jenkins的镜像。注意,要安装的是 jenkins/jenins:lts,不是jenins,后者已经被官方废弃了。
通过如下命令准备好环境:
$docker pull jenkins/jenkins:lts
$mkdir /appdata/jenkins
$chmod 777 /appdata/jenkins
$vi /install/create-jenkins.sh
最后一个命令打开的编辑器中,输入内容:
docker run -id -p 8080:8080 -p 50000:50000 --privileged=true --name jenkins -v /appdata/jenkins:/var/jenkins_home jenkins/jenkins:lts
执行如下命令启动容器:
$chmod 754 /install/docker/create-jenkins.sh
$/install/docker/create-jenkins.sh
$docker logs -f jenkins
最后,完成jenkins内部配置即可。
3. 问题与解决方案
3.1. nexus无法搜索代理仓库
启动后的nexus,没有自动下载被代理库(比如中央库)的索引,因此搜索没有结果。也没有向nexus2那样,提供主动下载远端库的选项。目前还没有找到办法。
==》2018-10-14更新:
因为前两天系统重装,我重新安装了docker并重配了nexus容器。结果这一次无法搜索代理仓库的问题自己消失了。
回忆并对比了一下两次安装过程的差异,估计前一次无法搜索的原因,在于那次安装没有结束的时候,就重启了nexus容器,导致nexus的初始化过程没有完全完成。
具体过程如下:
刚完成容器启动时,我没有看容器的日志,只是执行了docker ps命令,看到容器允许起来了,就在浏览器中访问nexus。结果发现nexus无法访问,就急躁的判断是启动失败,直接重启了容器。结果重启后,发现还是无法访问。这时才想到查看容器日志,结果发现了一大堆乱七八糟的异常。
不得已,只能删除nexus数据文件目录,删除nexus容器,然后重新创建容器。这一次,我吸取教训,一直开着log,果然经过了整整5分钟,才完成nexus初始化。等初始化完成后,才去访问界面,这一次成功进入。
再次完成nexus配置后,搜索 commons-lang3,成功搜索。
根据这个现象,初步估计上一次创建nexus容器,也没有等初始化彻底完成就重启了容器,当时虽然容器显示启动成功,也能访问界面,但不知道哪里的初始化过程被中断了,导致搜索maven-central失败。
3.2. jenkins启动后许多插件无法安装
原来安装docker时,没有使用 官方仓库的web界面,而是直接使用命令来搜索仓库并根据概述选择了jenkins这个镜像:
[root@wangqaing ~]# docker search jenkins
NAME DESCRIPTION STARS OFFICIAL
jenkins Official Jenkins Docker image 3858 [OK]
jenkins/jenkins The leading open source automation server 993
jenkinsci/jenkins Jenkins Continuous Integration and Delivery … 338
因为它被显示为官方构建的镜像。但安装完毕后,发现许多插件都报无法安装。
通过命令:
docker logs -f jenkins
查看日志,发现这些插件都说因为jenkins版本太低,建议从v2.60.3 升级到 v2.73.3或以上:
Oct 04, 2018 2:33:21 PM jenkins.InitReactorRunner$1 onTaskFailed
SEVERE: Failed Loading plugin Pipeline: Declarative v1.3.2 (pipeline-model-definition)
java.io.IOException: Pipeline: Declarative v1.3.2 failed to load.
- You must update Jenkins from v2.60.3 to v2.73.3 or later to run this plugin.
- Pipeline: Shared Groovy Libraries v2.12 failed to load. Fix this plugin first.
at hudson.PluginWrapper.resolvePluginDependencies(PluginWrapper.java:626)
at hudson.PluginManager$2$1$1.run(PluginManager.java:516)
at org.jvnet.hudson.reactor.TaskGraphBuilder$TaskImpl.run(TaskGraphBuilder.java:169)
at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:282)
at jenkins.model.Jenkins$7.runTask(Jenkins.java:1090)
at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:210)
at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
这就让我感到奇怪了。难道官方的镜像其实不是最新的吗?
我从官方仓库的web界面去搜索,才发现镜像 jenkins 的介绍里,说该镜像已经被deprecated了,官方建议使用 jenkins/jenins:lts
好吧。
先通过命令:
docker stop jenkins
停止jenkins容器运行。
再通过命令:
docker rm jenkins
删掉已安装的容器。
最后通过命令:
docker rmi jenkins
删掉旧镜像,重新下载并安装当前的推荐镜像:
docker pull jenkins/jenkins:lts
调整创建容器的脚本内容为:
ocker run -id -p 8080:8080 -p 50000:50000 --privileged=true --name jenkins -v /appdata/jenkins:/var/jenkins_home jenkins/jenkins:lts
清空并重建jenkins工作空间:
$rm -rf /appdata/jenkins
$mkdir /appdata/jenkins
$chmod 777 /appdata/jenkins
创建并启动jenkins容器:
$/install/docker/create-jenkins.sh
最后查看日志:
$jenkins logs -f jenkins
完成jenkins的配置并使用。
3.3. 容器时区和本地时区不一致
启动容器后,在查看日志时,偶尔发现容器内的时区和本地时区不一致,容器时间少了8个小时。
- 创建容器时就复制宿主的时区和本地时间到容器
最傻瓜的解决方案:在第一次允许 docker run 时,就已经意识到这个问题并将容器内地时区设置为和宿主机器的一样。
假如我要修改容器nexus的时区,那么:
$docker run -d -p 8081:8081 --name nexus -v /appdata/nexus:/nexus-data -v /etc/localtime:/etc/localtime sonatype/nexus3
$docker stop nexus
$docker start nexus
但事情往往没有这么理想。如果我们已经创建了容器,那么如何修改该容器的时区呢?
先进入容器命令行环境查看时间:
$docker exec -it nexus bash $date
然后退出容器命令行,在宿主命令行拷贝本地时区文件到容器:
$docker cp /etc/localtime jenkins:/etc/localtime
其中,第一个
/etc/localtime
是宿主机器上的文件;jenkins
是容器的名字,这里也可以用容器的id来替换;冒号后面的/etc/localtime
,是拷贝到docker容器后的路径。
现在,我们来验证一下:$date
可以看到,现在系统时间已经更改过来了。
但是我们如果在jenkins界面上看,会发现jenkins的时间,仍然比北京时间晚8个小时。如果进入 系统管理->系统信息 菜单,看“系统属性”列表的最后一个属性,可以看到其时区是 etc/UTC,这代表格林尼治时间。显然不对。
$cat /etc/timezone
可以看到显示内容也是 etc/UTC。也就是说jenkins容器的时区还需要修改。而该文件是ubuntu的文件,redhat系列的fedora上,是没有这个文件的。解决方案是在本地编辑一个timezone文件,其内容为:
Asia/Shanghai
然后再将该文件拷贝到容器内,覆盖原来的/etc/timezone文件,最后重启容器即可:
docker cp timezone jenkins:/etc/timezone docker restart jenkins
最后再次进入jenkins浏览器界面,会发现时区已经正常。
3.4. 启用docker的aliyun镜像加速
今天在拉去官方docker hub的镜像时,速度特别慢。正好我有阿里云的账户,又正好发现阿里云有docker的镜像加速服务,就使用了。具体过程是直接参考的阿里云的说明文档。
- 登录阿里云
-
进入容器镜像服务菜单:
容器镜像服务.png
- 选择镜像加速器,可以看到自己的专属加速器地址
- 配置docker使用镜像地址:
$cd /etc/docker $vi /etc/docker/daemon.json
将如下脚本写入 daemon.json:
{
"registry-mirrors": ["https://sa2gfpxw.mirror.aliyuncs.com"]
}
- 重启容器
$service docker stop $service docker start
好了,现在拉取镜像的速度飞起来了。