之前恒温告诉了我 selenium conf 2015 的消息,提到里面有个 docker 相关的 topic 。刚好我最近也在关注如何把 docker 应用到测试领域,所以去看了一下,收获不少。在此也把它记录成文字,以供大家了解。
我的博客上的地址:http://chjvps.com/blog/?p=997
视频地址:
youtube: https://www.youtube.com/watch?v=S4OkrnFb-YY&index=20&list=PLRdSclUtJDYXehIM7SyQyIghLDmE015Gc(需 ***)
youku: http://v.youku.com/v_show/id_XMTMzODY3MTI4MA==.html?f=26081500
Slide 地址:
https://speakerdeck.com/marekj/seconf2015-docker-selenium
国内网盘地址
演讲者:Marek Jastrzebaki (twitter: @rubytester)
主要内容(通过类别重新排序):
- 用虚拟机组建的 Selenium Grid 的痛处
- Github 上的 seleniumHQ/docker-selenium 项目
- docker 基本介绍
- 用 docker 代替虚拟机组建 Selenium Grid 的好处
- Marek 在 HomeAway 中的实践
- Demo
- 本地 standalone 的 Demo
- 本地 grid 的 Demo
- 云主机上 grid 的 Demo
用虚拟机组建的 Selenium Grid 的痛处
我们通过 puppet 或者 chef 来管理虚拟机,从而能尽快地进行虚拟机的部署和管理。然而还是存在下面这些问题:
- 需要根据测试环境需要增加/配置/删除虚拟机,耗费大量时间
- 没有找到好的策略来管理 chrome 这种会自动升级的浏览器(理想情况下应该有不同版本并能自由切换)
Github 上的 seleniumHQ/docker-selenium 项目
地址:https://github.com/SeleniumHQ/docker-selenium
简要说明:
- 包含了所有你运行 Selenium standalone/grid 所需的一切
- 使用 Dockerfile 配置 java,selenium jar,浏览器,浏览器对应 webdriver 等镜像内环境。这意味着你可以通过修改 Dockerfile 构建定制化的镜像
- 有部分包含了 VNC Server 的镜像用于调试。通过 VNC Viewer 连接进去即可看到浏览器画面进行调试。
包含的镜像及说明:
-
selenium/base: 包含 Java 运行组件及 Selenium jar 文件的基础镜像
-
selenium/hub: 运行 Selenium Grid Hub 的镜像
-
selenium/node-base: 包含虚拟桌面环境及 VNC 支持的 Selenium Grid Node 基础镜像
-
selenium/node-chrome: 包含 Chrome 的 Selenium node 镜像。需要连接 Selenium Grid Hub 使用。
-
selenium/node-firefox: 包含 firefox 的 Selenium node 镜像。需要连接 Selenium Grid Hub 使用。
-
selenium/standalone-chrome: 包含 Chrome 的 Selenium standalone 镜像(不需要连接 Selenium Grid Hub)
-
selenium/standalone-firefox: 包含 Firefox 的 Selenium standalone 镜像(不需要连接 Selenium Grid Hub)
-
selenium/standalone-chrome-debug: 包含 Chrome 和 VNC Server 的 Selenium standalone 镜像
-
selenium/standalone-firefox-debug: 包含 Firefox 和 VNC Server 的 Selenium standalone 镜像
-
selenium/node-chrome-debug: 包含 Chrome 和 VNC Server 的 Selenium Grid Node 镜像,需要连接 Selenium Grid Hub 使用
-
selenium/node-firefox-debug: 包含 Firefox 和 VNC Server 的 Selenium Grid Node 镜像,需要连接 Selenium Grid Hub 使用
同时也在 Docker Hub 上有对应的镜像库:

所有镜像使用 autobuild ,即 github 上的 Dockerfile 一旦更新,这个镜像库内的镜像也会自动更新。
Docker 基本介绍
关键字:Build, Ship, Run
-
Build
- 把应用及其依赖环境全部打包到一个标准单元(及 docker image)。可以使用 Dockerfile 来建立 image 。
- 这样你不用再关注你的环境配置是否正确,也不需要在一个 OS 中安装各个应用所需要的依赖库了。
-
Ship
- push 到 registry
- 公共 registry:Docker hub
- 从 registry pull image 到任何兼容 docker 的机器。把配置机器简化到只需要 pull 镜像即可。
- 采用 layer 存储 image 。layer 类似于 github 上的一次 commit ,每个 image 都是 layer 的叠加。pull image 只是 pull 你机器上没有的 layer ,已经有的不需要再获取。
-
Run
- Container 相当于 image 的运行环境。它把 image 全部加载进来并转化成运行环境来运行应用。
- Docker container 把一个应用及它运行所需要的一切封装在文件系统中。(Docker conatiners wrap up a piece of software in a complete filesystem that contains everything it needs to run.)
- 无论它在哪里运行,它的实际运行都是完全一样的。
- 由于不包含完整的 OS ,container 的启动和关闭都相当快速。

这里 Marek 举了一个例子:
把能运行 docker 的机器比作船,container 比作船上的货物。
人们总是关注这艘船能装多少货物,并让它尽可能处于最大负载量,结果就是船不堪重负,很有可能就沉了。
而对于 selenium
,我们需要的不是这种容量大的大船,我们也不关注它最大容量有多大。我们需要的是能快速装卸货物的快速船。如果货物放上去后可以正常使用,那很好。如果不能,那就把它扔了换另一个。这同时也是
selenium grid 的思想。
也就是说,我们不关注你给我们多大的船,多少艘船,也不关注这个船本身的型号什么的。我们需要的只是使用船上装卸货物的能力,所以给我们能装卸货物的船即可。
用 docker 代替虚拟机组建 Selenium Grid 的好处
- 不再需要自己安装 java,浏览器等,只需要按照需要 run 这些 docker image 即可。
- 只需要有一台 OS 支持 Docker Engine 的虚拟机/物理机就可以跑了
- 在 Home away 的实践中,我们在内部云上根据自己需要开启和组建自己的 selenium grid ,大大缩短了以前增加和配置虚拟机所花的时间。同时由于组建 grid 成本低,因此不需要 grid 的时候直接关闭即可。
Marek 在 HomeAway 中的实践
HomeAway 内部使用了 puppet 。我对这个东西基本没什么了解,所以仅贴上 slides :




欢迎了解 puppet 的童鞋在后面跟帖解读这部分内容。
Demo
本地 standalone 的 Demo
使用的镜像:selenium/standalone-firefox-debug
视频地址:http://youtu.be/vMba9xlDoOs(需 ***)
为了让翻不了墙的同学了解这个 Demo ,简要步骤记录如下:
1. 下载并运行镜像:

- 第一条命令启动了 container
-d
表示使用 daemon 形式运行,-name se
表示这个 container 名称为 se(便于以后控制),-p 5900:5900 -p 4444:4444
表示把 container 的 5900 和 4444 端口映射到宿主机的相同端口号,其中 5900 是 VNC Server 使用的端口,4444 是 standalone server 使用的端口
- 第二条命令检查 container 是否成功启动了
2. 打开 VNC


此处的 192.168.99.100 是运行 docker 的虚拟机的 ip 地址。这条命令在 mac os x 上适用,其他系统不一定也适用。但也可以手动通过 VNC Viewer 程序连接到虚拟机。
3. 运行脚本


脚本打开了 container 中的 firefox 浏览器,打开 Homeaway 搜索页,输入搜索信息进行搜索,最后关闭 firefox 浏览器。
4. 关闭 container

关闭之前打开的 container ,释放资源。
本地 grid 的 Demo
视频地址:http://youtu.be/hG5AOf8Pm4c(需 ***)
使用的镜像:
- selenium/hub
- selenium/node-chrome
- selenium/node-firefox
为了让翻不了墙的同学了解这个 Demo ,简要步骤记录如下:
1. pull 所有需要用到的镜像

2. 运行这些镜像

--link
表示这个 container 新启动的 container 能通过内部网络与指定 container 进行连接,即 node 能与 hub 建立网络通讯。
运行成功后应该能通过 docker logs hub
看到 hub container 中接收到两个 node 的注册请求:

使用 docker ps
命令能看到 3 个 container:

并且用浏览器打开 hub 地址后看到两个节点:

3. 运行脚本

hub 上的浏览器状态会发生变化:
exit 前:

exit 后:

云主机上 grid 的 Demo
这个 demo 没视频
环境配置:
- 两台 digital ocean 上具有独立 ip 地址的主机
- ocean1:作为 hub 主机
- ocean2:作为 node 主机

大致步骤:
$ docker-machine create \
--driver digitalocean \
--digitalocean-access-token $TOKEN \
ocean1
...
$ docker-machine create \
--driver digitalocean \
--digitalocean-access-token $TOKEN \
ocean2
...

2. 在 ocean1 上启动 hub container

3. 在 ocean2 上启动 node container


4. 最终效果

总结
- 对于 selenium grid 环境,Docker 相比 VM 的优势在于快速启动和快速部署
- 对于变更频繁的测试环境,使用 docker 能减少很多部署的时间
- 对于测试领域,docker 的实践更多在于替代虚拟机,降低部署成本
最后
如果觉得这篇文章对你有帮助,也愿意给我打个赏的同学,可以点击下方打赏按钮,扫描二维码打赏给我。在此谢过!
↙↙↙阅读原文可查看相关链接,并与作者交流