2016年11月20日星期日

Docker_009:使用 Jenkins 测试持续集成

环境:MAC OS  X 10.12.1 + Docker 1.12.3

架构设计:构建一个运行在 Docker 容器中的 Jenkins 服务器,测试应用作为 Jenkins 的一个作业,以 Docker 容器的方式递归地运行在以 Docker 容器的方式运行的 Jenkins 服务器 中。

Jenkins 作业使用 Docker 创建了一个镜像,而这个镜像使用仓库的 Dockerfile 管理和更新。
这样的设计不仅架构配置和代码可以同步更新,管理配置也变得很简单。
通过镜像创建了运行测试的容器,测试完成时,可以丢弃测试容器。

1. 构建 Jenkins 镜像
$ cd /Users/maping/mygit/dockerbook-code/code/5/jenkins

$ cat Dockerfile
FROM jenkins
MAINTAINER james@example.com
ENV REFRESHED_AT 2016-06-01

USER root
RUN apt-get -qqy update && apt-get install -qqy sudo
RUN echo "jenkins ALL=NOPASSWD: ALL" >> /etc/sudoers
RUN wget http://get.docker.com/builds/Linux/x86_64/docker-latest.tgz
RUN tar -xvzf docker-latest.tgz
RUN mv docker/* /usr/bin/

USER jenkins
RUN /usr/local/bin/install-plugins.sh junit git git-client ssh-slaves greenballs chucknorris

$ docker build -t jamtur01/dockerjenkins .

2. 运行 Jenkins 容器
$ docker run -p 8080:8080 --name jenkins --privileged -d jamtur01/dockerjenkins
说明:
--privileged 启动 Docker 的特权模式,允许容器以宿主机具有的权限来运行容器,包括访问宿主机的内核和设备。这是让我们可以在 Docker 中运行 Docker 的必要设置。

$ docker logs -f jenkins
INFO: Jenkins is fully up and running
访问 http://localhost:8080/ 提示你输入管理员口令,口令在 /var/jenkins_home/secrets/initialAdminPassword

$ docker exec -it jenkins bash

jenkins@309e0a788aae:/$ cat /var/jenkins_home/secrets/initialAdminPassword
1bbd854f84b04b93865e0fad6a5aff68

输入口令后,进入安装插件界面。

2.1 安装插件

选择 Install Suggested Plugin,这一步需要翻墙,否则很慢,且有些插件安装不成功。
建议在公司网络环境下一次性安装成功所有插件。

2.2 创建管理员
maping/maping maping930883@hotmail.com

$ docker stop jenkins
$ docker start jenkins

2.3 保存安装好插件的 jenkins image
$ docker commit jenkins maping930883/jenkins:2.19.1
$ docker save -o jenkins.2.19.1.tar maping930883/jenkins
$ gzip -v jenkins.2.19.1.tar

2.4 启动新的 jenkins image
$ docker stop jenkins
$ docker rm jenkins
$ docker rmi jamtur01/dockerjenkins
$ docker run -p 8080:8080 --name jenkins --privileged -d maping930883/jenkins:2.19.1

2.5 创建 Jenkins 作业
(1)创建一个自由风格的作业,命名为 Docker_test_job
(2)点击 Advanced...按钮,单击 Use Custom workspace,指定 Directory 为 /tmp/jenkins-buildenv/${JOB_NAME}/workspace 。
(3)在 Souce Code Management 区域里,选择 Git 并指定仓库为 https://github.com/jamtur01/docker-jenkins-sample.git 。
(4)单击 Add Build Step,选择 Execute shelll,shell 脚本内容如下:
# Build the image to be used for this job.
IMAGE=$(sudo docker build . | tail -1 | awk '{ print $NF }')

# Build the directory to be mounted into Docker.
MNT="$WORKSPACE/.."

# Execute the build inside Docker.
CONTAINER=$(sudo docker run -d -v $MNT:/opt/project/ $IMAGE /bin/bash -c 'cd /opt/project/workspace && rake spec')

# Attach to the container so that we can see the output.
sudo docker attach $CONTAINER

# Get its exit code as soon as the container stops.
RC=$(sudo docker wait $CONTAINER)

# Delete the container we've just used.
sudo docker rm $CONTAINER

# Exit with the same value as that with which the process exited.
exit $RC

这个脚本都做了什么呢?
首先,它使用 Git 仓库中的 Dockerfile 创建一个新的镜像。Dockerfile 内容如下:
  FROM ubuntu:14.04
  MAINTAINER James Turnbull "james@example.com"
  ENV REFRESHED_AT 2016-06-01
  RUN apt-get update
  RUN apt-get -y install ruby rake
  RUN gem install --no-rdoc --no-ri rspec ci_reporter_rspec
可以看出,这样构建出来的镜像可以用于测试 Ruby 且使用 RSpec 测试框架的应用。
接下来,创建一个包含 Jenkins 工作空间的目录,并把这个目录挂载到 Docker 容器,并在这个目录里执行测试。
然后使用 docker attach 命令进入容器,得到容器输出的内容。
然后使用 docker wait 命令,该命令会一直被阻塞,直到容器里的命令执行完毕,返回容器退出时的返回码。
最后,删除刚刚创建的容器,并使用容器的返回码退出。Jenkins 根据这个返回码得知作业的测试结果是成功还是失败。
(5)单击 Add post-build action,加入一个 Publish JUnit test result report (JUnit 测试结果报告)
在 Test report XMLs 域,指定 spec/reports/*.xml。这个目录是 ci_reporter gem 的 XML 输出位置。
Jenkins 会处理测试的历史结果并输出结果。

保存。

3. 运行 Jenkins 作业
第一次运行时,会下载构建基础镜像,会慢一些,下次运行时就快了。

运行时报告如下错误:
Cannot connect to the Docker daemon. Is the docker daemon running on this host?

没有评论: