本文来自网易云社区html
做者:叶子
java
学习docker搭建测试环境断断续续也有三个多月了,但愿记录一下这个过程。常言道,总结过去,展望将来嘛~文章浅显,还望各位大神路太轻拍。node
按照国际惯例,先说一下背景:linux
目前我所处的项目组不断扩大和发展,所以质量保障维度也须要不断扩展。然而多种质量保障维度的开展须要多套测试环境的支持,目前项目组里只有一套测试环境,按照传统方法一步步手工搭建测试环境费时费力,有什么方法能够迅速搭建环境呢?固然是近几年大火的docker啦。但是我是docker小白,以前只是简单地看过几篇docker入门的帖子,去官网上按照tutorial敲了一遍命令,但总感受是纸上谈兵,一到实战环节,依然无从下手。git
中国首富王健林说:“先定一个小目标“。咱们的项目里面除了java web应用就是java app应用,java web应用说白了就是tomcat么,之前本身手动部署过,看上去不会太难,那就从这个开始,先用docker部署一个项目中的tomcat应用好了。docker方面的知识是零基础,老大推荐了一本书叫《第一本docker书》。web
这本书浅显易懂,适合我这个小白,粗粗读完前4章后,我就感受本身能够上路了。redis
测试环境的应用模块部署都是在ndp平台上部署的,先简单了解下ndp平台部署web应用的原理,就是将代码从git上拉下来,编译打包好,找一台云主机,这台云主机上安装了jdk和tomcat,而后把打包好的代码放进tomcat里,设置下端口号,启动起来就行了。那若是用docker怎么部署呢?读完docker书就知道,其实一个docker容器就至关于一台云主机,咱们的云主机是linux系统,拉一个linux系统的镜像,启动这个镜像的容器后,我在里面装个jdk和tomcat,这不就和咱们的云主机环境如出一辙了嘛~ docker
到这里思路就清晰多了,第一步先搞个和云主机环境同样的docker容器,网上搜了一下后,发现直接就有现成的tomcat镜像,tomcat自己也依赖jdk,并且也是基于linux环境的,第一步立马就作完了,这速度杠杠滴。那接下来就是拉取代码,编译打包,而后放进去启动就能够了。因而乎,第一个问题就碰到了,代码是有权限的,不是随便就能够拉取的。回想之前在云主机上拉取代码,是在这台云主机上生成一对ssh密钥,而后把公钥上传到git lab上,这样就能得到拉取代码的权限了。都说实践是检验真理的惟一标准,赶忙在刚刚启动的docker容器里试了一把,恩,行得通!但是这才一个docker容器啊,若是我再来几个docker容器,每一个容器都要生成一对ssh密钥,而后上传,岂不累死。 怎么办呢?马克思主义哲学说道过,要透过现象看本质,git识别权限的本质是什么?是在于私钥和公钥的匹配!公钥在git服务器上,那我本地只要有对应的私钥就能够了呀,我在建立容器的时候把一个git已有的公钥所匹配的私钥放进去,这样容器就自带git权限了嘛。 数据库
代码拉下来之后,下一步就是编译打包,那先研究下ndp平台是怎么部署咱们测试环境的web应用的吧。看了一下,在ndp平台上找到了这个web应用的一个build.xml,咦,这不就是ant工具的执行脚本么,仔细一读,果真是个编译打包的脚本,其中关键的步骤是利用mvn clean install进行编译打包的。ok,那在刚刚启动的容器里安装一下ant和maven工具,而后用ant命令执行下这个build.xml,大功告成! 浏览器
执行完ant命令之后,发现生成了一个compressed的文件夹,里面主要是编译打包后生成的东西,以下图:
那么这些编译打包好的东西应该放在哪里呢?再一次研究一下ndp部署的tomcat应用的目录层级,内心估摸着我把docker容器中的目录层级弄得和ndp同样应该不会有什么问题。通过对比发现,compressed文件内容和测试环境tomcat应用的webroot文件内容是同样的,吼吼~
此外,其余目录层级不同的地方罗列了一下,大概有以下几个:
大体读了读,tomcat是个脚本文件,用于启动tomcat服务用的,里面调用了./default/tomcat、init-functions和ratatelogs文件,那就把这些须要的文件都拷贝过来,并确保tomcat脚本里全部的调用路径都正确。
另外还须要修改的server.xml,将docBase地址指定为compressed的绝对路径
将两边目录层级弄的如出一辙后,就到了见证奇迹的时刻,运行启动命令:
./tomcat start
查看日志发现正常启动,并没有异常报错,这真是个好兆头。再用浏览器试试是否能访问成功,看到预期的网页打开了:)至此,第一个用docker方式部署的web应用模块就完成啦
鉴于项目里有多个不一样的web模块,它们所依赖的基础环境都同样,所以打算构建一个基础镜像,将所须要的相同的配置文件都放入基础镜像中,而后各自模块的编译打包过程写成一个Dockerfile,这样就不用在容器里手敲命令进行编译打包了,Dockerfile伪代码以下:
FROM tomcat 基础镜像git clone 代码COPY build.xml, 配置文件等到容器里指定的路径RUN build.xml,生成打包文件COPY 打包文件 TO destination filestart 启动运行模块
web应用搞定后,接下来就是java app模块了。看了一下环境依赖,只须要装个jdk环境就行,而后ndp上一样有java app的构建脚本build.xml,再研究下npd部署的java app的目录结构,该拷贝的拷贝,该修改的修改,照猫画虎弄一遍,也启动成功了。
接下来就是优化下tomcat和java app这两个基础镜像,而后再写写各自模块的Dockerfile就好了
每一个模块都有本身的Dockerfile,这样就能迅速构建模块镜像并启动部署了。至此,利用docker部署项目的应用模块就完成了。
感谢上述过程当中提供大力帮助的集美貌与才华于一身的婷婷同窗~
--------------------
踩过的坑:
一、在执行build.xml脚本进行构建时,遇到相似以下的报错:
缘由是所须要的jar包由于在maven远程仓库中没法找到,首先检查一下在docker容器安装maven后,记得要把settings.xml设置成杭研的maven仓库,若是还遇到这样的错误,多是杭研maven仓库里没有该jar包,或者由于网络等其余问题,没法下载该jar包。基本上通用的jar包都能下载成功,有一些基于模块之间依赖的jar包没法下载到,若是你本地maven仓库里有这些jar包的话,能够拷贝进容器的maven仓库里,或者在容器里拉取相互依赖模块的代码,经过mvm clean install命令将其打包进容器的maven仓库里。
二、在容器里启动应用后,遇到没法连通redis的问题:
代码里填写的redis地址是云主机的私有ip地址,容器所在的宿主机与redis在不一样租户下,所以没法经过私有ip进行连通访问,容器的宿主机与redis同属于一个机房,可经过机房ip进行访问,与开发协商将代码里的依赖服务的ip地址都改成机房地址。
三、在docker容器里拷贝git hub的私钥后,执行git clone命令出现如下状况:
这个提示已经比较清楚了,.ssh/id_rsa 这个私钥文件权限 too open,修改私钥的权限:chmod 0600 id_rsa 后便可git clone代码了。
--------------------
然而好景不长,很快咱们就发现针对每一个应用模块写Dockerfile这种方式的不足,一是构建的镜像太多,每一个模块都要构建镜像,而后启动容器,镜像也比较大,很是占空间;二是因为咱们项目的特殊性,有些应用模块在构建时须要依赖别的项目的jar,当时为了图省事把依赖的jar直接放入基础镜像了,当依赖的jar发生变化时,个人基础镜像就要从新弄了,全部其余模块的镜像都要从新弄,这可要了命啊。看来此计不是长久之计,还需另谋出路。
通过以前的探索,咱们知道,ndp的部署模式是一盏指路明灯,以前就是照着ndp的部署脚本照葫芦画瓢过来的,那ndp平台是怎么解决不一样模块之间的打包依赖问题呢?粗粗研究了一下,发现ndp是统一在一个地方打包,而后将打包好的compressed文件分发到别的云主机上进行部署。那按照这个思路,咱们也找一台容器进行统一编译打包,而后分发到不一样的容器进行部署呗。
如此一来,咱们只须要三个基础镜像,一个是用来编译打包的镜像,只须要安装jdk,maven,ant等编译打包工程所依赖的工具,一个是tomcat镜像,一个是java环境镜像,再写一个脚本,伪代码以下:
get compressed file #对应模块的打包文件get config file #对应模块的部署配置文件start module #启动运行模块
如何获取对应的打包文件呢? wget 命令能够从远程服务器上下载文件,前提是不一样容器之间的网络须要互通。咱们能够本身手动建立一个docker网络,而后把不一样的容器都手动加入这个网络里,这样全部容器都在同一个网络里,应该就不存在网络不通的问题了。获取部署配置文件咱们采用了git pull方式,在git上维护全部模块的部署配置文件。
如此一来,当部署web模块的时候就以tomcat镜像来启动容器并同时运行脚本,部署java app模块的时候就以java app镜像启动容器并同时运行脚本,如此一来就不用给每一个模块写Dockerfile制做镜像了,也节省了很多构建镜像的空间。
不过虽然节省了构建镜像的空间,但容器运行的空间仍是要提供的。一台云主机的基本配置是4核 CPU,8GB 内存,而项目的模块多达20几个,所有模块放在一台云主机上可吃不消。确定要搞多台云主机做为一个集群,把容器部署到这个集群中。这时候就要用到容器编排工具了,编排工具负责如下几点:
选择最适合部署容器的机器,好比拥有最多空闲资源的机器
发生机器故障,能自动把故障机器上的容器部署到其它节点。
若是集群添加了新的机器,从新平衡容器的分配状况。
若是容器故障了,重启它。
...
Docker自己内置了容器编排功能,称为docker swarm mode。网上有不少关于docker swarm mode的资料,在此就很少阐述了,大体过程以下:
建立网桥:在每台云主机上建立docker_gwbridge网桥,注意,必须先建立网桥再建立swarm集群
建立集群:指定一台云主机做为manager,初始化swarm
加入集群:在其余云主机上运行docker swarm join命令,使其加入该swarm集群
建立服务:使用docker service create来建立service,相似docker run 命令,建立的时候可直接运行脚本,执行部署过程
使用docker service create命令建立服务的时候须要指定大量参数,每次都要敲好长的命令,能够用docker compose yaml模板,相似以下:
version: "3.2" services: compile: image: dockercloud/hello-world deploy: replicas: 1 placement: constraints: - node.hostname==docker-test ports: - "8080:8080" networks: - overlay_net networks: overlay_net: driver: overlay
至此,咱们解决了编译打包过程当中各个模块相互依赖的问题,经过docker swarm mode方式实现了应用模块集群化部署的方式,接下来的目标就是将这些应用模块依赖的其余基础服务拆分出来,如数据库,redis,zookeeper等等,那样子才算完整的一套独立的测试环境。
网易云容器服务为用户提供了无服务器容器,让企业可以快速部署业务,轻松运维服务。
网易云大礼包:https://www.163yun.com/gift
本文来自网易云社区,经做者叶子受权发布。
相关文章:
【推荐】 Lily-一个埋点管理工具
【推荐】 Amazon新一代云端关系数据库Aurora(上)
【推荐】 再也不任人欺负!手游安全的进阶之路