前端开发环境的复杂性越来越突出,unix(mac或linux)环境下相对问题不大,但windows环境下各种前端插件问题频出,尤其以node-sass等插件为代表,没碰到过几次翻来倒去还是npm install安装失败的前端不是老鸟前端。为了解决环境的一致性问题,docker被很多人引入了前端开发领域。但对于新人docker显然不是那么好上手,可能会碰到很多问题卡住很久甚至卡死,最近我也是因为重装系统碰到了环境不一致导致项目无法npm install成功的问题,虽然最后解决了但仍然很苦恼,所以开始研究docker,并将心得体会整理出来分享给大家,期望能帮助更多人。
目的
下面开始长篇大论,不想看的可以跳过直接往下拉看docker使用配置指南。
显然我的目标是搭建一个完善的前端开发环境和生产环境(受限于公司内部阻力,生产环境可能暂时无法docker化,所以暂时只是研究下方案,作为技术储备)。
为了实现这个目的,需要满足以下几个条件:
1.打造统一的环境,包括系统类型、版本、node版本,并能所有人方便的使用同一套环境。
2.方便操作,不能增加使用成本。
3.使用现有的硬件条件,不能新增设备(毕竟我们只是切图仔,要求额外的设备公司也不会答应啊),性能消耗不能大。
经过简单而又谨慎的调研后,显然docker能够满足我们的这几个条件。
如何打造统一的环境
docker的使用模式基本上是宿主机上跑容器,宿主机就是我们的windows主机或者Mac主机,相信类似我们公司这样因为不愿意花钱买正版直接让研发用ubuntu的少之又少吧,容器其实就可以简单的理解为虚拟机,在这里我们不过于深入的讲解docker的原理,重在使用。
一般来讲,除去开发的ide之外,我们搭建开发环境需要安装node,git等工具,拉取项目代码,安装依赖包,然后还要解决一系列因为网络或者系统环境带来的不确定性问题。
而使用docker后,开发者们只需要安装好docker软件,一个命令启动容器,就可以进行开发了,环境配置等等都已经提前配置好了,不需要开发者再去自己处理。当然,我们都使用过虚拟机,知道大概的使用情况,假如docker和虚拟机一样,那我们也不会选择它。有了统一的环境后,我们还需要解决一些问题,这些问题在虚拟机上无法解决或者解决起来很麻烦。
1.如何在本地预览页面?
2.如何在本机编辑文件,并同步到开发机?
第一个问题很好解决,虚拟机上我们可以配置ip地址或者端口映射,docker上我们也可以进行端口映射到宿主机,从而直接进行访问。
第二个问题在虚拟机上很难解决,有人提过Samba映射的方案,不过配置麻烦,而且体验并不十分的好,而这一点通过docker的volumn共享文件特性可以轻易地解决。这个具体的使用方式后续会写。
docker优势
这一点尤其重要,大家都很清楚,只有最傻瓜式,最无脑使用的东西才能推广开,不然即使再好的东西也只能沦为小众甚至被淘汰。
总结一个开发者需要做的事情:
入职当天,安装各种开发用的软件,各种依赖包,环境配置等等,基本上消耗的时间与开发经验成反比,一天到一周不等。
然后在平时的开发中,标准的开发流程是拉取项目代码,安装依赖包,ide写代码,浏览器看效果,build验证,提交代码,安装一些新的依赖包,协同开发者各自安装 依赖。
我们可以看到,此时会有两个问题,
1.新人入职的环境配置是个较大的问题,不过一般而言并不会很受重视,毕竟新人此时也不是很熟悉项目,就当熟悉项目了。
2.日常开发中,安装依赖包是个很大的隐患,且与项目的人员规模成正比,当环境复杂到一定程度后,代码在不同环境下的表现也会出现一定的差异性。
下面说说docker环境下的开发者工作流程:
入职当天,安装好自己惯用的ide工具和docker软件,下载好内部镜像包,一个命令启动,开始干活,好吧其实还是要熟悉下代码,不过已经可以边改bug边熟悉代码了,毕竟互联网行业我们要大干快上(认真脸),而且网上看到有人做过分析,docker的性能优于虚拟机,所以可以放心使用(毕竟也没有更好的办法了)。
docker使用配置指南
主要分三块
1.制作开发用镜像。
2.使用镜像进行日常开发。
3.制作发布镜像测试环境及线上环境发布。
开始前,我们需要先熟悉下docker的一些常用命令。
docker pull 镜像:tag ##拉取远程仓库tag版本号的镜像
docker images ##查询本地仓库的所有镜像
docker rmi 镜像id ##删除镜像
docker tag 镜像id 镜像:TAG ##重命名镜像
docker run -it --privileged -d --name developer --rm imageId ##根据本地某个镜像创建一个容器
docker ps ##查询本地容器
docker ps -a ##查询本地所有运行的容器
docker rm containerId ##删除容器
docker attach containerId ##进入容器,需要先start容器或者docker run创建容器
docker export 容器id > x:/xx/xx.tar ##导出容器快照
docker import - x:/xx/xx.tar ##导入容器快照
docker save 镜像id -o x:/xx/xx.tar ##导出镜像
docker load -i x:/xx/xx.tar ##导入镜像
一、 制作开发镜像
- docker pull ubuntu 从官方仓库拉取一个ubuntu的基本镜像(需要切换下源地址,官方的源地址是国外地址,下载速度感人)。
- docker run 打开容器,并进入容器的命令行界面,进行一些基本环境的配置,如node,git,项目代码拉取,依赖安装等。
- 环境配置好之后docker commit 生成新的镜像,作为后续开发者使用的基础镜像。
- 导出镜像文件,托管并分享给相应的开发者,导出镜像应使用docker export直接导出容器镜像,避免因为携带镜像的层信息而使镜像过大。
二、 使用镜像进行日常开发
- 下载自己开发项目对应的镜像(公司内部托管文件下载很快,之所以不使用Dockfile也是因为这个问题,生成镜像太过依赖网速了)。
- docker run 打开容器,在命令中配置volumn共享路径,把宿主机的源码文件/src映射到容器中的对应/src路径上,同时还要在命令中加上端口映射,可以在本机直接浏览器打开页面看到效果,这样就可以本地修改文件,容器内文件同步变更(本质上是同一份文件),此处有坑,前端的热更新hmr在容器下会失效,需要修改配置,具体可以看下这篇文章,详细地介绍了相应的热刷新的文件监控知识,重点是对应的watchOptions配置项中的poll属性,angular项目可在start命令中设置poll属性的时间,单位为毫秒,例如 --poll 1000。
- 此时已经可以愉快的进行开发了。
三、 制作部署用镜像
因为我们公司部署不使用docker,所以还是git提交代码后,Jenkins构建项目。下面大致讲一下docker部署的流程,因为生产环境服务器一般网络都会比较好,所以可以忽略网络问题,此时可以使用Dockerfile来进行构建。
# Dockerfile文件内容
FROM node:alpine as builder
ENV PROJECT_ENV production
ENV NODE_ENV production
# http-server 不变动也可以利用缓存
WORKDIR /code
ADD package.json /code
RUN npm install --production
ADD . /code
RUN npm run build
# 选择更小体积的基础镜像
FROM nginx:alpine
COPY --from=builder /code/public /usr/share/nginx/html
- 在项目的根目录下创建一份Dockerfile文件,使用多阶段构建,减小最终的镜像文件大小。
- 使用docker build命令在生产环境主机上生成最终的镜像,或使用相应的docker自动化构建系统进行自动构建,然后用镜像生成对应的容器,发布成功。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。