本文转载自微信公众号“东方儿”,作者:东方儿。转载本文请联系东方儿公众号。这篇文章是一个过渡。在开发用例管理模块之前,需要先将介绍文章中开发的代码部署到Linux系统Docker中,并完成部署流程。这个过程对后端设计有着决定性的影响。本地运行通过在Vue项目中执行npmrunserve,在Django项目中执行pythonmanage.pyrunserver,我们在本地运行项目,示意图如下:前端在本地启动一个Node服务器,后端启动一个Django本地服务器分别使用8080和8000端口。浏览器有同源策略:只有域名、端口、协议一致才能访问,否则会因为跨域访问而被浏览器拦截。图中前后端端口不一致,存在跨域,前端无法直接请求后端。解决方法是在vue.config.js中配置devServer:这是一个Node开启的代理服务器。前端向后端请求时,会先发送给Node代理服务器,Node代理服务器向真正的后端服务器发送相同的参数。发出请求并将响应返回给前端。在本项目中,前端请求还是发送到http://127.0.0.1:8080,浏览器不会拦截,Node代理服务器会帮你转发请求到后端8000端口。Nginxdeployment了解了本地运行的proxy转发,我们来看看Nginxdeployment。Nginx本身就是一个服务器,就像Node服务器一样,也可以看成是ApacheTomcat。Vue项目使用npmrunbuild命令将代码构建成dist目录下的静态文件,加载到Nginx服务器中。结合Docker的示意图如下:与本地运行相比,部署Nginx时,前端变化很大。一:将dist的静态文件拷贝到/usr/share/nginx/html目录下,二:对于/路径,Nginx会监听80端口;三:对于/api路径,Nginx会将请求转发到后端服务器端口,也称为反向给代理。后端没有变化。为了看起来和本地操作有点不同,端口略有变化。Docker在内部使用端口80。这里的关键是理解Dockerteprunner-frontend、Dockerteprunner-backend和Linux之间的关系。如果你不知道Docker,你应该听说过虚拟机。从概念上讲,Docker就像一个虚拟机。这三位可以看作是三位宿主。Linux的IP为172.16.25.131,80端口映射到Dockerteprunner-frontend的80端口,8099端口映射到Dockerteprunner-backend的80端口,如图下方双向箭头所示.在linux上访问http://127.0.0.1可以打开登录页面,但是无法向后台发起请求,因为从80端口直接请求8099端口是跨域的。解决方法是在Dockerteprunner-frontend上使用Nginx作为反向代理,先将请求发送到Nginx服务器,再转发到Linux的8099端口。在dockerteprunner-frontend中不能设置/api的proxy为http://127.0.0.1:8099,因为这个Docker容器的8099端口没有开启,但是linux机器上的8099端口是开启的,所以需要通过IP来指定。整体思路清晰了,接下来就是动手操作了。编写deploy脚本前端打开teprunner-frontend文件夹,新建deploy/nginx.conf文件:/路径从user/share/nginx/html读取文件,入口为index.html,转发/api到http://172.16.25.131:8099。这个文件将被复制到Docker镜像中。新建Dockerfile:FROM定义了基础镜像,可以理解为操作系统,前端工程基于nginx构建。WORKDIR定义了镜像当前的工作目录,也就是在进行后续的COPY操作时使用哪个镜像目录。COPY将dist静态文件和nginx.conf配置文件分别复制到镜像中。COPY命令的第一个参数是本地目录,第二个参数是镜像目录。镜像目录由WORKDIR指定,本地目录由Docker上下文指定。新建build.sh文件:DockerContext指定Docker上下文为teprunner-frontend根目录。这里的Shell脚本有两个阶段,第一阶段使用node编译:dockerrun#runimage--rm#运行后删除容器-v$(pwd)/../:/data/src#$(pwd)指当前工作目录,挂载根目录到data/src-v/root/.npm/_logs:/root/.npm/_logs#挂载日志文件-w/data/src/#镜像当前工作目录$BUILDER_IMAGE#运行image为node:latest,使用node编译前端代码/bin/sh-c"npminstall&&npmrunbuild"#/bin/sh为shell可执行程序,第二阶段调用执行npm命令,打包成一个Docker镜像:dockerbuild#buildimage-f$Dockerfile#指定Dockerfile文件的位置-t$PkgName#Image包名$DockerContext#Dockercontextbackendbackend也类似,先创建一个deploy/Dockerfile文件:backend项目基于python:3.8搭建,然后设置时区,COPY..直接将Django源文件复制到镜像目录/app/release,执行RUN命令pipinstall命令安装依赖包。CMD和RUN是有区别的。RUN命令在docker构建时执行,CMD命令在dockerrun时执行,预定义的启动命令。这样就简化了迁移数据库等启动命令,服务器数据库和本地一样。新建一个build.sh文件:Python代码不需要编译,可以打包成Docker镜像。部署到Ubuntu系统DockerLinux系统是内核版本,它有很多发行版本,比如CentOS、Ubuntu,本文使用Ubuntu,只有一个原因,它看起来不错。我的大学室友一时冲动把Windows系统换成了Ubuntu,每天都在向我们展示它的酷炫和强大。过了两三天,发现office不灵了,玩不了游戏,就又换回来了。哈哈,Ubuntu一般都是玩玩的,除非你是做Linux内核开发的。下载软件:VMware破解版UbuntuDesktop20.04安装过程这里不再赘述。打开Ubuntu虚拟机:打开Terminal,输入su,输入密码,发现权限不足切换到root:su。安装curl:apt-getinstallcurl安装docker:curl-fsSLhttps://get.docker.com|bash-sdocker--mirrorAliyun使用ifconfig查询虚拟机IP:不要选择.git和node_modules文件夹,压缩teprunner-前端包。不要选择.git和__pycache__文件夹,将teprunner-backend打成压缩包。将前后端压缩包复制到虚拟机Documents中解压:UbuntuDesktop的优点是提供了图形化的操作界面,适合像我这样的新手用户。使用命令行编辑工具vi或者图形化编辑工具gedit将teprunner-frontend/deploy/nginx.conf文件中的/api转发地址编辑为你虚拟机的实际IP地址:打开两个Terminal,cd到teprunner-frontend/deploy和对于teprunner-backend/deploy,执行./build.sh命令。如果执行时报^M之类的错误,是因为在Windows中编辑后复制到Linux中的格式不一致。使用apt-getinstalldos2unix命令安装工具并进行格式转换,如dos2unixbuild.sh和dos2unixDockerfile。前端搭建截图:第一次会比较慢,因为需要下载node依赖包和拉取nginx镜像,但是第二次会快很多。后台搭建截图:第一次因为需要拉取python镜像会比较慢,但是第二次会快很多。构建完成后,输入dockerimages命令可以看到打包好的Docker镜像:启动前端镜像:dockerrun-p80:80teprunner-frontend启动后端镜像:dockerrun-p8099:80teprunner-backend镜像启动后,成为一个Docker容器,可以理解为一个虚拟主机。-p参数用于映射Ubuntu端口和Docker端口。可以加上-d参数让容器在后台运行。dockerps-a查看容器,dockerkillCONTAINER或dockerstopCONTAINER退出容器。最后在虚拟机中访问http:127.0.0.1即可登录,如果本机要访问,需要将127.0.0.1改为你虚拟机的实际IP,比如http://172.16。25.131。总结本文首先介绍本地运行和Nginx部署的示意图,涉及到跨域访问和反向代理。然后编写部署脚本,编译代码,构建镜像。最后部署到Ubuntu系统的Docker中运行。在使用的过程中,我也感受到了Docker这项划时代技术的魅力。如果没有Docker,我们需要在Ubuntu上安装nginx、node、python等软件。有了Docker,我们只需要安装Docker,其他的都基于Docker镜像。就是这样。teprunner测试平台的用例是代码的形式,这就涉及到代码存放位置的问题。为了调用和执行pytest,它必须存储在文件中。本文的实践给出了重要的提示。如果后端直接将代码写入磁盘文件,每次镜像打包部署时,保存的用例代码都会被抹掉。解决这个问题的第一种方式是使用K8S,第二种方式是将代码存入数据库。学习版使用第二种方式保存数据库,执行时动态从数据库中取代码生成文件。第一种方法供参考:最后简单说一下Docker和K8S。Docker是Docker的,K8S是Google的,Docker是个小公司。在创建之初,并没有考虑“容器编排”的功能。2014年,谷歌推出Kubernetes,解决大规模场景下Docker容器编排问题。2016年,Kubernetes发布了CRI统一接口。Docker虽然在2016年也发布了DockerSwarm,但是带来了Docker的多主机多容器编排方案。解决方案,但一直无法阻止K8S赢得容器编排大战。参考资料:https://www.cnblogs.com/riwang/p/11883332.htmlhttps://zhuanlan.zhihu.com/p/334787180https://testerhome.com/topics/27860
