Docker 测试开发之路 (工具篇)--Docker

孙高飞 · October 17, 2016 · Last by 孙高飞 replied at November 16, 2018 · 4822 hits
本帖已被设为精华帖!

前言

之前在《环境管理》那一篇分享中介绍了我在管理环境上的一些经验,但是并没有介绍docker的使用细节。但有些小伙伴们还是比较感兴趣的。关于docker的教程网上其实也是满天飞,各种命令和原理的文章,中文的英文的数不胜数。所以我就不从安装开始,介绍各种命令了。这么讲我觉得我也讲不出什么花来,但是网上的这些教程大多数都是理论层次的。他们告诉你这么命令是干什么的,却没有用一条线把他们穿起来告诉你怎么用他们。所以今天我来用我们在测试中实际遇到的例子给大家穿一条线出来。让没用过docker的小伙伴们大概知道docker是怎么用的,有多简单,通过例子把大概的概念和理论了解一下。 这样就不会被漫天高大上的专有名字搞懵逼了。

什么是docker

官网上和各类文章中都对docker作出了明确的阐释,但是这些定义过于专业和高大上了。所以他姥爷这个土鳖就用俺们村的大白话给大家说一下。

Docker 这个单词英文原意是码头工人,搬运工的意思,这个搬运工搬运的是各种应用。docker是一种容器技术。有的小伙伴们不了解什么是容器的话就把它当虚拟机吧。虽然docker不是虚拟机,但是大家可以把它当成虚拟机用。我们把各种应用(例如我们测试环境中的各种服务)制作成镜像(镜像制作很简单) ,docker这个搬运工要搬运的东西就是这个镜像,它可以启动一个或者N个容器并把镜像搬运进去,这就是为什么我在《环境管理》那篇分享中可以一下子启动近30套测试环境的原因。只要我有镜像,在任何有docker服务的机器中都可以迅速拉起N套测试环境来。

在demo中学习

干说概念性的东西容易让人懵逼。我们还是像学习编程从hello world开始一样,我们先演示一个demo,从迅速搭建一个test link应用开始。

mysql

首先我们需要一个mysql服务来存储test link的数据。按照上面说的,我们需要一个mysql镜像。 那么我们如何制作镜像呢? docker的好处之一就是共享,他人制作的镜像我们可以下载下来直接使用。怎么做呢? 我们可以去docker hub中直接搜寻mysql的官方镜像

具体的使用细节官方镜像附带的说明中写的很清楚,很简单。我们来用一下吧。首先是下载mysql 5.5的镜像。命令如下:

docker pull mysql:5.5

运行过后我们下载了镜像. docker pull 这条命令就是在docker hub上搜寻并下载一个镜像。接下来我们运行一下 docker images | grep mysql 来查看本地下载的mysql镜像。docker images的意思就是列出所有的镜像。

OK,我们有了mysql的镜像了,那么我们怎么使用这个镜像呢。 来来来,我们关键的地方到了。请看下面的脚本

export name=testlink_mysql
export ip=172.27.1.221

docker rm -f $name
docker run --name=$name -e MYSQL_ROOT_PASSWORD=root -itd -v /home/testlink_data:/var/lib/mysql --net=none mysql:5.5

pipework br0 $name $ip/20@172.27.0.1

接下来我们讲解一下这些命令。从docker rm -f开始把,这条命令是删除一个容器,还记得什么是容器么? 容器是镜像的载体。我们的镜像要放在容器里运行的。所以如果有同名的容器我们先删除它,当然这一步不是必须得。 接下来我们看docker run的命令, 这条命令就是用镜像去启动一个容器,命令的最后的那个mysql:5.5就是镜像的名称(我们之前用docker pull下载的),是不是很简单。这样我们就启动了这个mysql的服务了。当然中间有一些参数我来详细的讲解一下。

  1. --name:定义容器的名称。我们可以通过docker ps来查看所有容器。
  2. -e: 启动容器时向容器内传递一个环境变量,这个参数可以有多个。 这是非常重要的一个参数,有些时候我们在制作镜像的时候并不清楚一些行为到底要怎么定义,需要在启动容器的时候决定。例如这个例子里我们用-e 向mysql容器传递了root的密码。mysql容器在启动的时候会读取这个环境变量并设置root密码
  3. -v: 这同样是一个很重要的参数,它是一个挂载的概念。是在主机和容器间共享数据的方式。用:分割,左边是宿主机的文件目录,右边是容器的目录。这个参数在我们做数据备份的时候很有用。在这个例子我把mysql存储数据的目录挂载到了主机的一个目录里。这样就算容器被人不小心删除了,数据也不会丢失的。
  4. --net:这个参数指定docker的网络模式,我一般设置为none,因为我要分配固定ip 最后一个命令,pipework,它是一个第三方的工具,可以给容器分配固定ip。有兴趣的可以在网上搜一下这个工具的使用。

OK,运行这个脚本后,我们的数据库服务就搭建好了。是不是很简单。你不是运维的同学,你不必懂mysql得配置,你只需要下载官方镜像直接使用就可以了。

接下来我们搞一搞test link吧。同样现在docker hub上搜一下有没有人已经做好了test link的镜像。很幸运的我发现也是有的。我们运行一下docker pull otechlabs/testlink下载即可。我们同样用下面的命令启动test link容器

export name=testlink_new
export ip=172.27.1.220

docker rm -f $name
docker run -itd --name=$name --hostname=$name --net=none -v /home/testlink_upload:/var/testlink testlink

pipework br0 $name $ip/20@172.27.0.1

命令跟上面mysql一样,也很简单,唯一需要注意的是我挂载目录的位置是test link保存附件的文件夹,testlink不是所有数据都保存在数据库里的,所以这部分也要挂载出来保存。容器启动后,我们使用ip登录test link,见证奇迹的时刻就到了。剩下的你只需要根据test link的页面配置一下数据库了。到这里我们就搭建了一个在测试工作中很常见的用例管理工具。当然到了这里我们还有些不太完美。就是到了这里我们的数据虽然都挂载到宿主机上保存了。但是test link的配置缺没有,这是容器启动后,我们在页面上配置的。这部分的信息我们没有保存。所以我们需要修改一下镜像了。如下:

FROM otechlabs/testlink

ADD files /var/www/testlink

这是一个Dockerfile,制作镜像的语法文件。我们使用Dockerfile的语法来扩展一个镜像。 第一行的FROM 命令大家看到了,说明是继承自另一个镜像的。也就是说我们对test link镜像做扩展。熟悉编程的小伙伴们理解起来一定很容易,你就把它当成面向对象语言中的继承就行了。 接下来我们用ADD命令,把宿主机中的 files文件夹下所有的文件都copy 到镜像中的/var/www/testlink 文件夹中。 这里说一下我把test link的config文件存在了files文件中,所以也就是说config文件现在被copy到了test link容器里了。接下来我们运行一个简单的命令构建镜像。

docker build -t testlink .

这是构建一个惊险的命令,要在Dockerfile的目录下执行。这样我们新的镜像就做好了。我们用新的镜像代替之前启动test link的旧镜像。一切就OK了,完美了。test link的配置文件也就存到了镜像里了。

这是一个搭建test link的简单应用。我们经理了下载官方镜像并使用的过程,扩展镜像满足我们自己需要的过程。 我们可以用这个思想搭建各种基础服务。那下面我们再说复杂一点的场景

更复杂点的场景

现在说说我们的测试环境,要搭建测试环境肯定就没有那么成熟的镜像给我们用了。我们需要自己专门定制一个镜像出来,首先我们要做一个基础镜像,解决依赖的问题,例如我们的产品是java的项目,那我们要装:maven,jdk,git,ssh等等。下面看一下Dockerfile的例子:

FROM docker.io/ludalex/docker-java7-maven-aws-git
MAINTAINER sungaofei(sungaofei@4paradigm.com)

ADD files /root

RUN apt-get update \
&& apt-get install wget -y \
&& apt-get install -y openssh-server \
&& /etc/init.d/ssh start \
&& apt-get install -y oracle-java7-set-default \
&& cd /tmp \
&& wget http://apache.claz.org/thrift/0.9.3/thrift-0.9.3.tar.gz \
&& tar -zxvf thrift-0.9.3.tar.gz \
&& cd thrift-0.9.3 \
&& ./configure && make \
&& make install \
&& cd /opt \
&& mkdir web \

大家看到首先我还是继承了一个从docker hub上下载的基础镜像,通过名字就可以看出来,这个基础镜像里已经有了maven,git之类的东西。但还不够,我们需要再下载一点东西。RUN 这个命令就是执行shell 命令的。 它最大的作用就是安装一些依赖包。在RUN里面,最常用的就是apt-get了。上面的例子我下载并安装了ssh的组件包,jdk7,thrift的RPC框架包等等。然后再运行一个 docker built -t 我们就做好这个基础镜像了,这解决了我们的依赖问题。以后再制作任何java镜像我们都可以通过扩展这个基础镜像来做。
接下来我们看一下部署镜像的Dockerfile

FROM 4paradigm/dango2.0-test-base-new
ADD files /root

ENTRYPOINT ["/root/entrypoint.sh"]

可以看到这个镜像貌似没干什么。但是,恩? ENTRYPOINT 是个什么鬼? 这个很重要,非常重要。大家记住了,这是启动容器后第一个运行的命令。也就是说,它是容器的启动命令,它是容器启动后干的第一个事。我们通常把启动服务的脚本放在这里。我们同ADD 命令把一些启动脚本放在容器的/root目录下。然后通过ENTRYPOINT,运行启动脚本。我们来看一下entrypoint.sh这个脚本都干了什么

cd /root
echo "setup is running"

# deploy simba
cd /opt/web

git clone git@git.4paradigm.com:prophet/simba.git


cd /opt/web/simba
git checkout ${simba_branch}

if [ -n ${simba_commit_id} ]
then
echo "reset to commit_id ${simba_commit_id}"
git reset ${simba_commit_id}
fi

mvn -DskipTests clean package -U

cd /opt/web
./startserver.sh

中间我删除了一些干扰代码,真实的情况比这个复杂些。看到这个脚本里我们拉取了git上的代码。编译并运行了启动脚本。大家注意这里我读取了一些环境变量,例如${simba_branch},这就是通过启动容器的时候(也就是docker run)的 -e的参数传递进来的环境变量。 这样我们就做到了容器的参数化。接下来我们运行 docker run就可以了,我们的这个java项目的测试环境的搭建起来了。当然我中间刻意忽略了一些细节免得大家被干扰。但是我们用docekr搭建测试环境的流程大概就是这样的了。

总结

今天他姥爷就讲到这里吧,我用了两个在工作中用到docker的简单例子来给各位扫一下盲。特别详细的教程他姥爷真的木有时间写了,大家去翻官方文档吧,平时工作比较忙。女王大人还怀孕了,而且女王大人对我这种老是坐在电脑面前码字或者撸代码不管老婆孩子的行为很是不满了。所以各位见谅,我的这个系列文章真的没办法很详细的写个教程。就是带大家入个门,让大家看一下大概怎么做的,做成什么样子。很多细节大家要自己探索和阅读文档了。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 24 条回复 时间 点赞

不错,学习了

敢问一声,孙大师想来杭州发展?跳槽不

#2楼 @hu_qingen 额,媳妇已然怀孕了~ 这个阶段实在不想折腾了~~

#3楼 @ycwdaaaa 能理解,我也经历过这个阶段,😀 😀 等孙大师啥时候有想法了,找俺啊,很希望跟你一起共事下😀 😀

#4楼 @hu_qingen 恩恩 好的~

加精理由: 普及了docker这个devops依赖的基础知识.

思寒_seveniruby 将本帖设为了精华贴 18 Oct 11:45

windows系统下使用docker安装testlink,数据库启动正常的,账号设置也是正常的,遇到以下报错:

TestLink setup will now attempt to setup the database:

Creating connection to Database Server:Failed!
Please check the database login details and try again.
Database Error Message: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

请问下有遇到过没,怎么解决的?

#8楼 @jaychang1989 就是连接不上数据库。 你连的local的数据库。但是local的环境里没有启动数据库的服务

#9楼 @ycwdaaaa 我在本地连数据库localhost:32770,数据库是可以连接成功的,testlink里面也是配置localhost:32770,就会出现报错,很奇怪

#10楼 @jaychang1989 你换个远程的试试

#10楼 @jaychang1989 话说端口号感觉怪怪的呢。。。。mysql不应该是3306么

想问下 docker可以运行c++的exe不 ?

#14楼 @piaodangdang 这个跟docker没关系。。跟操作系统有关系。。 exe只能windows跑吧,所以要在docker里启动windows的系统。不过在linux下的docker是不能启动windows系统的容器的,因为它不是虚拟机,只是容器而已。 听说微软出的一个产品封装了docker,可以制作windows镜像

#15楼 @ycwdaaaa 这个我试过了 一个nanoserver的基础镜像就8个G 什么都没干 这完全背离了docker轻量化的要求 在segementFault有人说过可以运行exe 但是没查到相关资料 后来segmentfault不知道为什么访问不了了 看大神的docker管理文档 就来问问有木有相关部署经验

#16楼 @piaodangdang 这个我也木有经验了。 看国外的docker大会上说有个程序员妹子把docker改了,可以装windows。但我估计咱们是做不成了

呵呵,文章写的确实不错。很赞👍

不错!

请问一下,你们实际部署的时候 只部署需要测试的服务呢,还是把所有依赖的服务都部署一遍呢?

Sasha0609 回复

都可以~

pipework is probably never going to work on a Mac. 刚入门docker,请问除了pipework还有给容器分配固定ip的工具么?

弗多 回复

那就没听说过了~

孙高飞 回复

意思是windows系统上的docker只能运行windows操作系统以及它的程序?我想在win10上启动win7或者win8系统可行吗?网上的镜像拉取下来启动不起来。还有就是dockers和真机环境测试效果一样吗,因为我知道虚拟机和真机测试结果是有差别的。liunx版docker和window版docker差别有点大哦,window版docker底层要启动一个虚拟机。liunx版是内核原生支持,那是不是window版docker跟其实就是虚拟机模拟出来的呢

红客联盟 回复

怎么说呢, 你就记住一句话吧。 目前docker只能跑在linux内核上。 所以linux能做的它能做, linux做不了的,他绝对做不了。 你再windows上看到的一切都是假象。 虽然我听说微软在开发windows的docker,但是还没听说他们搞出来

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up